diff --git a/.cargo/audit.toml b/.cargo/audit.toml new file mode 100644 index 000000000..255dbf904 --- /dev/null +++ b/.cargo/audit.toml @@ -0,0 +1,24 @@ +[advisories] +ignore = [] +informational_warnings = ["unmaintained"] +severity_threshold = "low" + +[database] +path = "~/.cargo/advisory-db" +url = "https://github.com/RustSec/advisory-db.git" +fetch = true +stale = false + +[output] +deny = ["unmaintained"] # exit on error if unmaintained dependencies are found +format = "terminal" +quiet = false +show_tree = true + +[target] +arch = "x86_64" +os = "linux" + +[yanked] +enabled = true +update_index = true diff --git a/.changelog/unreleased/breaking-changes/1140-sanitize-abci-slice-accessors.md b/.changelog/unreleased/breaking-changes/1140-sanitize-abci-slice-accessors.md new file mode 100644 index 000000000..a10855668 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1140-sanitize-abci-slice-accessors.md @@ -0,0 +1,4 @@ +- `[rpc]` Change data accessor methods `abci::Data::value` and + `abci::Log::value` to `Data::as_bytes` and `Log::as_str`, + returning a byte array slice and a string slice respectively. + ([#1140](https://github.com/informalsystems/tendermint-rs/pull/1140)) diff --git a/.changelog/unreleased/breaking-changes/1144-update-config-v0.35.md b/.changelog/unreleased/breaking-changes/1144-update-config-v0.35.md new file mode 100644 index 000000000..99bf6a68e --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1144-update-config-v0.35.md @@ -0,0 +1,2 @@ +- `[tendermint-config]` Update supported Tendermint configuration file format to + v0.35 ([#1144](https://github.com/informalsystems/tendermint-rs/pull/1144)) \ No newline at end of file diff --git a/.changelog/unreleased/bug-fixes/1132-allow-omitted-fields-in-abci_info.md b/.changelog/unreleased/bug-fixes/1132-allow-omitted-fields-in-abci_info.md new file mode 100644 index 000000000..3f79fbd3a --- /dev/null +++ b/.changelog/unreleased/bug-fixes/1132-allow-omitted-fields-in-abci_info.md @@ -0,0 +1,4 @@ +- `[tools/proto-compiler]` Annotate serde to fall back to `Default` for the + omitted fields when deserializing `tendermint_proto::abci::ResponseInfo` struct, + also providing deserialization for the response at the `/abci_info` RPC endpoint. + ([#1132](https://github.com/informalsystems/tendermint-rs/issues/1132)) diff --git a/.changelog/unreleased/dependencies/1133-replace-serde-cbor.md b/.changelog/unreleased/dependencies/1133-replace-serde-cbor.md new file mode 100644 index 000000000..aaac2195c --- /dev/null +++ b/.changelog/unreleased/dependencies/1133-replace-serde-cbor.md @@ -0,0 +1 @@ +- `[light-client]` Replace `serde_cbor` with `serde_json` in `light_client` dependencies ([#1133](https://github.com/informalsystems/tendermint-rs/pull/1133)). \ No newline at end of file diff --git a/.changelog/unreleased/features/1134-proto-grpc.md b/.changelog/unreleased/features/1134-proto-grpc.md new file mode 100644 index 000000000..525f186ff --- /dev/null +++ b/.changelog/unreleased/features/1134-proto-grpc.md @@ -0,0 +1,2 @@ +- `[tendermint-proto]` Add a feature flag and generate gRPC server definitions + ([#1134](https://github.com/informalsystems/tendermint-rs/issues/1134)) diff --git a/.changelog/unreleased/features/1134-sign-request-conversion.md b/.changelog/unreleased/features/1134-sign-request-conversion.md new file mode 100644 index 000000000..9ea50f762 --- /dev/null +++ b/.changelog/unreleased/features/1134-sign-request-conversion.md @@ -0,0 +1,3 @@ +- `[tendermint]` Added conversions from signing requests to consensus states + and private key signing + ([#1134](https://github.com/informalsystems/tendermint-rs/issues/1134)) \ No newline at end of file diff --git a/.changelog/unreleased/features/1134-validator-crate.md b/.changelog/unreleased/features/1134-validator-crate.md new file mode 100644 index 000000000..76085b2e3 --- /dev/null +++ b/.changelog/unreleased/features/1134-validator-crate.md @@ -0,0 +1,2 @@ +- Added validator crate as per ADR-011 + ([#1134](https://github.com/informalsystems/tendermint-rs/issues/1134)) diff --git a/.changelog/v0.24.0-pre.1/breaking-changes/1027-light-client-verifier.md b/.changelog/v0.24.0-pre.1/breaking-changes/1027-light-client-verifier.md new file mode 100644 index 000000000..2af2cf74c --- /dev/null +++ b/.changelog/v0.24.0-pre.1/breaking-changes/1027-light-client-verifier.md @@ -0,0 +1,5 @@ +- `[tendermint-light-client]` Split out the verification functionality from the + `tendermint-light-client` crate into its own `no_std`-compatible crate: + `tendermint-light-client-verifier`. This helps move us closer to `no_std` + compliance in both tendermint-rs and ibc-rs + ([#1027](https://github.com/informalsystems/tendermint-rs/issues/1027)) diff --git a/.changelog/v0.24.0-pre.1/breaking-changes/1030-remove-chrono.md b/.changelog/v0.24.0-pre.1/breaking-changes/1030-remove-chrono.md new file mode 100644 index 000000000..7d8385ee5 --- /dev/null +++ b/.changelog/v0.24.0-pre.1/breaking-changes/1030-remove-chrono.md @@ -0,0 +1,11 @@ +- `[tendermint]` Reform `tendermint::Time` + ([#1030](https://github.com/informalsystems/tendermint-rs/issues/1030)): + * The struct content is made private. + * The range of acceptable values is restricted to years 1-9999 + (as reckoned in UTC). + * Removed conversions from/to `chrono::DateTime`. + * Changes in error variants: removed `TimestampOverflow`, replaced with + `TimestampNanosOutOfRange`; removed `ChronoParse`, replaced with `TimeParse`. +- `[tendermint-rpc]` Use `OffsetDateTime` and `Date` types provided by the `time` crate + in query operands instead of their `chrono` counterparts. + ([#1030](https://github.com/informalsystems/tendermint-rs/issues/1030)) diff --git a/.changelog/v0.24.0-pre.1/breaking-changes/1040-rpc-remove-server-error.md b/.changelog/v0.24.0-pre.1/breaking-changes/1040-rpc-remove-server-error.md new file mode 100644 index 000000000..20adc552e --- /dev/null +++ b/.changelog/v0.24.0-pre.1/breaking-changes/1040-rpc-remove-server-error.md @@ -0,0 +1,2 @@ +- `[tendermint-rpc]` Remove the `ErrorDetail::Server` variant + ([#1039](https://github.com/informalsystems/tendermint-rs/issues/1039)) diff --git a/.changelog/v0.24.0-pre.1/breaking-changes/1041-box-large-fields-in-enums.md b/.changelog/v0.24.0-pre.1/breaking-changes/1041-box-large-fields-in-enums.md new file mode 100644 index 000000000..017f6243a --- /dev/null +++ b/.changelog/v0.24.0-pre.1/breaking-changes/1041-box-large-fields-in-enums.md @@ -0,0 +1,6 @@ +- `[tendermint]` Box a large field value in `evidence::Evidence` + ([#1041](https://github.com/informalsystems/tendermint-rs/pull/1041)) +- `[tendermint-light-client]` Box large field values in `fork_detector::Fork` + ([#1041](https://github.com/informalsystems/tendermint-rs/pull/1041)) +- `[tendermint-rpc]` Box a large field value in `event::EventData` + ([#1041](https://github.com/informalsystems/tendermint-rs/pull/1041)) diff --git a/.changelog/v0.24.0-pre.1/breaking-changes/1046-p2p-ed25519-consensus.md b/.changelog/v0.24.0-pre.1/breaking-changes/1046-p2p-ed25519-consensus.md new file mode 100644 index 000000000..cf384a26f --- /dev/null +++ b/.changelog/v0.24.0-pre.1/breaking-changes/1046-p2p-ed25519-consensus.md @@ -0,0 +1,3 @@ +- `[tendermint-p2p]` All public APIs using `ed25519- + dalek` types now use types from `ed25519-consensus` + ([#1046](https://github.com/informalsystems/tendermint-rs/pull/1046)) \ No newline at end of file diff --git a/.changelog/v0.24.0-pre.1/breaking-changes/862-035-tendermint.md b/.changelog/v0.24.0-pre.1/breaking-changes/862-035-tendermint.md new file mode 100644 index 000000000..2aca57362 --- /dev/null +++ b/.changelog/v0.24.0-pre.1/breaking-changes/862-035-tendermint.md @@ -0,0 +1,2 @@ +- Updated integration testing to test against Tendermint v0.35.0 + ([#862](https://github.com/informalsystems/tendermint-rs/issues/862)) \ No newline at end of file diff --git a/.changelog/v0.24.0-pre.1/breaking-changes/862-abci-domain-types.md b/.changelog/v0.24.0-pre.1/breaking-changes/862-abci-domain-types.md new file mode 100644 index 000000000..220b52dc6 --- /dev/null +++ b/.changelog/v0.24.0-pre.1/breaking-changes/862-abci-domain-types.md @@ -0,0 +1,2 @@ +- `[tendermint]` Added domain types for ABCI + ([#862](https://github.com/informalsystems/tendermint-rs/issues/862)) \ No newline at end of file diff --git a/.changelog/v0.24.0-pre.1/breaking-changes/862-abci-wire-protocol.md b/.changelog/v0.24.0-pre.1/breaking-changes/862-abci-wire-protocol.md new file mode 100644 index 000000000..48248614a --- /dev/null +++ b/.changelog/v0.24.0-pre.1/breaking-changes/862-abci-wire-protocol.md @@ -0,0 +1,3 @@ +- `[tendermint-abci]` Changed low-level wire encoding protocol to + accommodate + ([#862](https://github.com/informalsystems/tendermint-rs/issues/862)) \ No newline at end of file diff --git a/.changelog/v0.24.0-pre.1/breaking-changes/862-rpc-event-events.md b/.changelog/v0.24.0-pre.1/breaking-changes/862-rpc-event-events.md new file mode 100644 index 000000000..9b35a6b37 --- /dev/null +++ b/.changelog/v0.24.0-pre.1/breaking-changes/862-rpc-event-events.md @@ -0,0 +1,5 @@ +- `[tendermint-rpc]` The `event::Event::events` field is now represented as + `Option>` as opposed to `Option>>` to accommodate breaking change in Tendermint v0.35.0 + subscription interface ([#862](https://github.com/informalsystems/tendermint- + rs/issues/862)) \ No newline at end of file diff --git a/.changelog/v0.24.0-pre.1/breaking-changes/862-rpc-tx-hash-hex.md b/.changelog/v0.24.0-pre.1/breaking-changes/862-rpc-tx-hash-hex.md new file mode 100644 index 000000000..bfaf2d85b --- /dev/null +++ b/.changelog/v0.24.0-pre.1/breaking-changes/862-rpc-tx-hash-hex.md @@ -0,0 +1,3 @@ +- `[tendermint-rpc]` The `/tx` endpoint now encodes + the `hash` parameter as hexadecimal instead of base64 + ([#862](https://github.com/informalsystems/tendermint-rs/issues/862)) \ No newline at end of file diff --git a/.changelog/unreleased/bug-fixes/1014-fix-proto-compiler.md b/.changelog/v0.24.0-pre.1/bug-fixes/1014-fix-proto-compiler.md similarity index 100% rename from .changelog/unreleased/bug-fixes/1014-fix-proto-compiler.md rename to .changelog/v0.24.0-pre.1/bug-fixes/1014-fix-proto-compiler.md diff --git a/.changelog/unreleased/bug-fixes/1016-lowercase-node-id.md b/.changelog/v0.24.0-pre.1/bug-fixes/1016-lowercase-node-id.md similarity index 100% rename from .changelog/unreleased/bug-fixes/1016-lowercase-node-id.md rename to .changelog/v0.24.0-pre.1/bug-fixes/1016-lowercase-node-id.md diff --git a/.changelog/v0.24.0-pre.1/dependencies/1046-ed25519-consensus-dep.md b/.changelog/v0.24.0-pre.1/dependencies/1046-ed25519-consensus-dep.md new file mode 100644 index 000000000..d505cda2b --- /dev/null +++ b/.changelog/v0.24.0-pre.1/dependencies/1046-ed25519-consensus-dep.md @@ -0,0 +1,3 @@ +- `[tendermint, tendermint-p2p]` Replaced the `ed25519-dalek` dependency with + `ed25519-consensus` + ([#1046](https://github.com/informalsystems/tendermint-rs/pull/1046)) diff --git a/.changelog/v0.24.0-pre.1/dependencies/1068-remove-native-tls.md b/.changelog/v0.24.0-pre.1/dependencies/1068-remove-native-tls.md new file mode 100644 index 000000000..c30a52c07 --- /dev/null +++ b/.changelog/v0.24.0-pre.1/dependencies/1068-remove-native-tls.md @@ -0,0 +1,3 @@ +- `[tendermint-rpc]`: Switch `hyper-proxy` to use `rustls`, eliminating + the only use of `native-tls` in tendermint-rs dependencies + ([#1068](https://github.com/informalsystems/tendermint-rs/pull/1068)) diff --git a/.changelog/v0.24.0-pre.1/improvements/1023-ed25519-deprecations.md b/.changelog/v0.24.0-pre.1/improvements/1023-ed25519-deprecations.md new file mode 100644 index 000000000..375daa0e4 --- /dev/null +++ b/.changelog/v0.24.0-pre.1/improvements/1023-ed25519-deprecations.md @@ -0,0 +1,3 @@ +- `[tendermint]` Deprecated `signature::ED25519_SIGNATURE_SIZE` + in favor of `Ed25519Signature::BYTE_SIZE` + ([#1023](https://github.com/informalsystems/tendermint-rs/issues/1023)) \ No newline at end of file diff --git a/.changelog/v0.24.0-pre.1/improvements/1030-new-time-api.md b/.changelog/v0.24.0-pre.1/improvements/1030-new-time-api.md new file mode 100644 index 000000000..a9c269f0d --- /dev/null +++ b/.changelog/v0.24.0-pre.1/improvements/1030-new-time-api.md @@ -0,0 +1,11 @@ +- Remove dependencies on the `chrono` crate. + ([#1030](https://github.com/informalsystems/tendermint-rs/issues/1030)) +- `[tendermint]` Improve `tendermint::Time` + ([#1030](https://github.com/informalsystems/tendermint-rs/issues/1030)): + * Restrict the validity range of `Time` to dates with years in the range + 1-9999, to match the specification of protobuf message `Timestamp`. + Add an `ErrorDetail` variant `DateOutOfRange` to report when this + restriction is not met. + * Added a conversion to, and a fallible conversion from, + `OffsetDateTime` of the `time` crate. + * Added `Time` methods `checked_add` and `checked_sub`. diff --git a/.changelog/v0.24.0-pre.1/improvements/1054-derive-hash-on-time.md b/.changelog/v0.24.0-pre.1/improvements/1054-derive-hash-on-time.md new file mode 100644 index 000000000..c7dfd4af7 --- /dev/null +++ b/.changelog/v0.24.0-pre.1/improvements/1054-derive-hash-on-time.md @@ -0,0 +1,2 @@ +- `[tendermint]` `Hash` is implemented for `tendermint::Time` + ([#1054](https://github.com/informalsystems/tendermint-rs/pull/1054)) diff --git a/.changelog/v0.24.0-pre.1/improvements/1077-private-key-clone.md b/.changelog/v0.24.0-pre.1/improvements/1077-private-key-clone.md new file mode 100644 index 000000000..234d4ffb3 --- /dev/null +++ b/.changelog/v0.24.0-pre.1/improvements/1077-private-key-clone.md @@ -0,0 +1,2 @@ +- `[tendermint]` Implement `Clone` for `PrivateKey` + ([#1077](https://github.com/informalsystems/tendermint-rs/issues/1077)) \ No newline at end of file diff --git a/.changelog/v0.24.0-pre.1/summary.md b/.changelog/v0.24.0-pre.1/summary.md new file mode 100644 index 000000000..91c578f54 --- /dev/null +++ b/.changelog/v0.24.0-pre.1/summary.md @@ -0,0 +1,12 @@ +*Jan 13, 2022* + +This pre-release targets Tendermint Core v0.35 and introduces a number of +breaking changes from the v0.23 series of tendermint-rs. We provide a +pre-release here so people can start experimenting with and preparing for +Tendermint v0.35 compatibility, but a number of refinements need to be made +before we can produce a v0.24.0 release. + +One of the major changes involves the introduction of [domain types for +ABCI](https://github.com/informalsystems/tendermint-rs/pull/1022) in preparation +for the release of ABCI++ in Tendermint v0.36. It also includes a number of +fixes and backports from the v0.23.x series of tendermint-rs. diff --git a/.changelog/v0.24.0-pre.2/breaking-changes/1064-infallible-encode_vec.md b/.changelog/v0.24.0-pre.2/breaking-changes/1064-infallible-encode_vec.md new file mode 100644 index 000000000..f403b9ab6 --- /dev/null +++ b/.changelog/v0.24.0-pre.2/breaking-changes/1064-infallible-encode_vec.md @@ -0,0 +1,2 @@ +- `[tendermint-proto]` Make `Protobuf::encode_vec()` infallible + ([#1064](https://github.com/informalsystems/tendermint-rs/issues/1064)) \ No newline at end of file diff --git a/.changelog/v0.24.0-pre.2/breaking-changes/1084-rpc-probe-gaia.md b/.changelog/v0.24.0-pre.2/breaking-changes/1084-rpc-probe-gaia.md new file mode 100644 index 000000000..51d74fe7e --- /dev/null +++ b/.changelog/v0.24.0-pre.2/breaking-changes/1084-rpc-probe-gaia.md @@ -0,0 +1,3 @@ +- `[tools/rpc-probe]` CLI updated to support probing Gaia nodes in addition + to kvstore-based Tendermint nodes to generate static fixtures for RPC tests + ([#1084](https://github.com/informalsystems/tendermint-rs/pull/1084)) \ No newline at end of file diff --git a/.changelog/v0.24.0-pre.2/breaking-changes/953-async-light-client.md b/.changelog/v0.24.0-pre.2/breaking-changes/953-async-light-client.md new file mode 100644 index 000000000..4bbd1d357 --- /dev/null +++ b/.changelog/v0.24.0-pre.2/breaking-changes/953-async-light-client.md @@ -0,0 +1,2 @@ +- `[tendermint-light-client]` Replace Io with async variant + ([#953](https://github.com/informalsystems/tendermint-rs/issues/953)) diff --git a/.changelog/v0.24.0-pre.2/dependencies/1097-contracts-dep.md b/.changelog/v0.24.0-pre.2/dependencies/1097-contracts-dep.md new file mode 100644 index 000000000..25be0a54c --- /dev/null +++ b/.changelog/v0.24.0-pre.2/dependencies/1097-contracts-dep.md @@ -0,0 +1,3 @@ +- `[tendermint-light-client]` Upgrade + [`contracts`](https://crates.io/crates/contracts) dependency to v0.6.2 + ([#1097](https://github.com/informalsystems/tendermint-rs/pull/1097)) \ No newline at end of file diff --git a/.changelog/v0.24.0-pre.2/dependencies/1113-prost-0.10.md b/.changelog/v0.24.0-pre.2/dependencies/1113-prost-0.10.md new file mode 100644 index 000000000..3ed8ee3da --- /dev/null +++ b/.changelog/v0.24.0-pre.2/dependencies/1113-prost-0.10.md @@ -0,0 +1,2 @@ +- Update `prost` to v0.10 ([#1113](https://github.com/informalsystems/tendermint- + rs/issues/1113)) \ No newline at end of file diff --git a/.changelog/v0.24.0-pre.2/features/1105-chain-id-constants.md b/.changelog/v0.24.0-pre.2/features/1105-chain-id-constants.md new file mode 100644 index 000000000..5923e5b90 --- /dev/null +++ b/.changelog/v0.24.0-pre.2/features/1105-chain-id-constants.md @@ -0,0 +1,2 @@ +- `[tendermint]` Add `tendermint::chain::Id::new` with support for chain ID constants + ([#1105](https://github.com/informalsystems/tendermint-rs/issues/1105)). diff --git a/.changelog/v0.24.0-pre.2/features/832-block-by-hash.md b/.changelog/v0.24.0-pre.2/features/832-block-by-hash.md new file mode 100644 index 000000000..28f17c6b3 --- /dev/null +++ b/.changelog/v0.24.0-pre.2/features/832-block-by-hash.md @@ -0,0 +1 @@ +- `[tendermint-rpc]` Add support for the `/block_by_hash` RPC endpoint. See for details ([#832](https://github.com/informalsystems/tendermint-rs/issues/832)). diff --git a/.changelog/v0.24.0-pre.2/summary.md b/.changelog/v0.24.0-pre.2/summary.md new file mode 100644 index 000000000..ac304b505 --- /dev/null +++ b/.changelog/v0.24.0-pre.2/summary.md @@ -0,0 +1,4 @@ +*May 4, 2022* + +The major change in this pre-release is the introduction of a fully `async` +light client interface. diff --git a/.changelog/v0.24.0-pre.2/workarounds/1021-rpc-block_results.md b/.changelog/v0.24.0-pre.2/workarounds/1021-rpc-block_results.md new file mode 100644 index 000000000..b0b563110 --- /dev/null +++ b/.changelog/v0.24.0-pre.2/workarounds/1021-rpc-block_results.md @@ -0,0 +1,4 @@ +- `[tendermint-rpc]` Allow deserialization of public keys from validator updates + from `block_results` endpoint in multiple JSON formats until this is fixed in + Tendermint + ([#1021](https://github.com/informalsystems/tendermint-rs/issues/1021)) diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index d4e0c19b5..9d5d9db0c 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -3,13 +3,18 @@ name: Bug report about: Create a report to help us squash bugs! labels: bug --- + +Version(s) of tendermint-rs: + +### What went wrong? + -**Steps to reproduce** +### Steps to reproduce -**What's the definition of "done" for this issue?** +### Definition of "done" diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md index b1ae83b08..d7f2238e4 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.md +++ b/.github/ISSUE_TEMPLATE/enhancement.md @@ -3,6 +3,11 @@ name: Enhancement about: A request for a new feature, or to enhance existing functionality labels: enhancement --- + +Version(s) of tendermint-rs: + +### Description + -**What's the definition of "done" for this issue?** +### Definition of "done" diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index c3c0debff..94b07728c 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,8 +1,13 @@ diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4b22d53fa..a6fe9718b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,6 +8,7 @@ on: - "docs/**" branches: - master + - 'v*.*.*' jobs: cleanup-runs: runs-on: ubuntu-latest diff --git a/.github/workflows/no-std.yaml b/.github/workflows/no-std.yaml new file mode 100644 index 000000000..3efe54e6f --- /dev/null +++ b/.github/workflows/no-std.yaml @@ -0,0 +1,33 @@ +name: no_std check +on: + pull_request: {} + push: + branches: master + +jobs: + check-no-std-panic-conflict: + name: Check no_std panic conflict + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + - run: | + cd tools/no-std-check + make check-panic-conflict + + check-substrate: + name: Check no_std substrate support + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + target: wasm32-unknown-unknown + override: true + - run: | + cd tools/no-std-check + make check-substrate diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 615d72b76..f7822468e 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -8,6 +8,7 @@ on: - "docs/**" branches: - master + - 'v*.*.*' jobs: cleanup-runs: runs-on: ubuntu-latest @@ -23,7 +24,8 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: stable + toolchain: nightly + components: rustfmt override: true - uses: actions-rs/cargo@v1 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8ad3e8ea8..7a0b9c9cd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,6 +8,7 @@ on: - "docs/**" branches: - master + - 'v*.*.*' jobs: cleanup-runs: runs-on: ubuntu-latest @@ -125,7 +126,7 @@ jobs: runs-on: ubuntu-latest services: tendermint: - image: informaldev/tendermint:0.34.13 + image: informaldev/tendermint:0.35.0 ports: - 26656:26656 - 26657:26657 @@ -143,28 +144,20 @@ jobs: env: RUST_LOG: debug - nightly-coverage: + coverage: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - profile: minimal - toolchain: nightly-2021-11-10 - override: true - - uses: actions-rs/cargo@v1 - with: - command: test-all-features - env: - RUSTFLAGS: '-Zinstrument-coverage' - LLVM_PROFILE_FILE: '%p-%m.profraw' - - name: Install grcov - run: | - rustup component add llvm-tools-preview - curl -L https://github.com/mozilla/grcov/releases/download/v0.8.2/grcov-linux-x86_64.tar.bz2 | tar jxf - - - name: Run grcov - run: | - ./grcov . --source-dir . --binary-path ./target/debug/ --output-type lcov --output-path ./lcov.info --branch --ignore-not-existing - - name: Upload to Codecov - run: | - bash <(curl -s https://codecov.io/bash) -f ./lcov.info + toolchain: stable + components: llvm-tools-preview + - name: Install cargo-llvm-cov + uses: taiki-e/install-action@cargo-llvm-cov + - name: Generate code coverage + run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v1 + with: + files: lcov.info + fail_ci_if_error: true diff --git a/.rustfmt.toml b/.rustfmt.toml index ff119513c..3b97eb30a 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,12 +1,19 @@ unstable_features = true # comments -comment_width = 100 +comment_width = 110 +normalize_comments = true wrap_comments = true # imports +group_imports = "StdExternalCrate" +imports_granularity = "Crate" reorder_imports = true # strings format_strings = false max_width = 100 +match_block_trailing_comma = true + +trailing_comma = "Vertical" +trailing_semicolon = true diff --git a/CHANGELOG.md b/CHANGELOG.md index 35a38bee6..9b825c46e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,140 @@ # CHANGELOG +## v0.24.0-pre.2 + +*May 4, 2022* + +The major change in this pre-release is the introduction of a fully `async` +light client interface. + +### BREAKING CHANGES + +- `[tendermint-light-client]` Replace Io with async variant + ([#953](https://github.com/informalsystems/tendermint-rs/issues/953)) +- `[tendermint-proto]` Make `Protobuf::encode_vec()` infallible + ([#1064](https://github.com/informalsystems/tendermint-rs/issues/1064)) +- `[tools/rpc-probe]` CLI updated to support probing Gaia nodes in addition + to kvstore-based Tendermint nodes to generate static fixtures for RPC tests + ([#1084](https://github.com/informalsystems/tendermint-rs/pull/1084)) + +### DEPENDENCIES + +- `[tendermint-light-client]` Upgrade + [`contracts`](https://crates.io/crates/contracts) dependency to v0.6.2 + ([#1097](https://github.com/informalsystems/tendermint-rs/pull/1097)) +- Update `prost` to v0.10 ([#1113](https://github.com/informalsystems/tendermint- + rs/issues/1113)) + +### FEATURES + +- `[tendermint-rpc]` Add support for the `/block_by_hash` RPC endpoint. See for details ([#832](https://github.com/informalsystems/tendermint-rs/issues/832)). +- `[tendermint]` Add `tendermint::chain::Id::new` with support for chain ID constants + ([#1105](https://github.com/informalsystems/tendermint-rs/issues/1105)). + +### WORKAROUNDS + +- `[tendermint-rpc]` Allow deserialization of public keys from validator updates + from `block_results` endpoint in multiple JSON formats until this is fixed in + Tendermint + ([#1021](https://github.com/informalsystems/tendermint-rs/issues/1021)) + +## v0.24.0-pre.1 + +*Jan 13, 2022* + +This pre-release targets Tendermint Core v0.35 and introduces a number of +breaking changes from the v0.23 series of tendermint-rs. We provide a +pre-release here so people can start experimenting with and preparing for +Tendermint v0.35 compatibility, but a number of refinements need to be made +before we can produce a v0.24.0 release. + +One of the major changes involves the introduction of [domain types for +ABCI](https://github.com/informalsystems/tendermint-rs/pull/1022) in preparation +for the release of ABCI++ in Tendermint v0.36. It also includes a number of +fixes and backports from the v0.23.x series of tendermint-rs. + +### BREAKING CHANGES + +- Updated integration testing to test against Tendermint v0.35.0 + ([#862](https://github.com/informalsystems/tendermint-rs/issues/862)) +- `[tendermint-rpc]` The `/tx` endpoint now encodes + the `hash` parameter as hexadecimal instead of base64 + ([#862](https://github.com/informalsystems/tendermint-rs/issues/862)) +- `[tendermint]` Added domain types for ABCI + ([#862](https://github.com/informalsystems/tendermint-rs/issues/862)) +- `[tendermint-abci]` Changed low-level wire encoding protocol to + accommodate + ([#862](https://github.com/informalsystems/tendermint-rs/issues/862)) +- `[tendermint-rpc]` The `event::Event::events` field is now represented as + `Option>` as opposed to `Option>>` to accommodate breaking change in Tendermint v0.35.0 + subscription interface ([#862](https://github.com/informalsystems/tendermint- + rs/issues/862)) +- `[tendermint-light-client]` Split out the verification functionality from the + `tendermint-light-client` crate into its own `no_std`-compatible crate: + `tendermint-light-client-verifier`. This helps move us closer to `no_std` + compliance in both tendermint-rs and ibc-rs + ([#1027](https://github.com/informalsystems/tendermint-rs/issues/1027)) +- `[tendermint]` Reform `tendermint::Time` + ([#1030](https://github.com/informalsystems/tendermint-rs/issues/1030)): + * The struct content is made private. + * The range of acceptable values is restricted to years 1-9999 + (as reckoned in UTC). + * Removed conversions from/to `chrono::DateTime`. + * Changes in error variants: removed `TimestampOverflow`, replaced with + `TimestampNanosOutOfRange`; removed `ChronoParse`, replaced with `TimeParse`. +- `[tendermint-rpc]` Use `OffsetDateTime` and `Date` types provided by the `time` crate + in query operands instead of their `chrono` counterparts. + ([#1030](https://github.com/informalsystems/tendermint-rs/issues/1030)) +- `[tendermint-rpc]` Remove the `ErrorDetail::Server` variant + ([#1039](https://github.com/informalsystems/tendermint-rs/issues/1039)) +- `[tendermint]` Box a large field value in `evidence::Evidence` + ([#1041](https://github.com/informalsystems/tendermint-rs/pull/1041)) +- `[tendermint-light-client]` Box large field values in `fork_detector::Fork` + ([#1041](https://github.com/informalsystems/tendermint-rs/pull/1041)) +- `[tendermint-rpc]` Box a large field value in `event::EventData` + ([#1041](https://github.com/informalsystems/tendermint-rs/pull/1041)) +- `[tendermint-p2p]` All public APIs using `ed25519- + dalek` types now use types from `ed25519-consensus` + ([#1046](https://github.com/informalsystems/tendermint-rs/pull/1046)) + +### BUG FIXES + +- `[tools/proto-compiler]` Fixed our proto-compiler, which was producing + protos that did not compile due to an incorrect Prost field annotation + ([#1014](https://github.com/informalsystems/tendermint-rs/issues/1014)) +- `[tendermint]` The `tendermint::node::Id` `Display` implementation now prints the hexadecimal string in lowercase ([#971](https://github.com/informalsystems/tendermint-rs/issues/971)) + +### DEPENDENCIES + +- `[tendermint, tendermint-p2p]` Replaced the `ed25519-dalek` dependency with + `ed25519-consensus` + ([#1046](https://github.com/informalsystems/tendermint-rs/pull/1046)) +- `[tendermint-rpc]`: Switch `hyper-proxy` to use `rustls`, eliminating + the only use of `native-tls` in tendermint-rs dependencies + ([#1068](https://github.com/informalsystems/tendermint-rs/pull/1068)) + +### IMPROVEMENTS + +- `[tendermint]` Deprecated `signature::ED25519_SIGNATURE_SIZE` + in favor of `Ed25519Signature::BYTE_SIZE` + ([#1023](https://github.com/informalsystems/tendermint-rs/issues/1023)) +- Remove dependencies on the `chrono` crate. + ([#1030](https://github.com/informalsystems/tendermint-rs/issues/1030)) +- `[tendermint]` Improve `tendermint::Time` + ([#1030](https://github.com/informalsystems/tendermint-rs/issues/1030)): + * Restrict the validity range of `Time` to dates with years in the range + 1-9999, to match the specification of protobuf message `Timestamp`. + Add an `ErrorDetail` variant `DateOutOfRange` to report when this + restriction is not met. + * Added a conversion to, and a fallible conversion from, + `OffsetDateTime` of the `time` crate. + * Added `Time` methods `checked_add` and `checked_sub`. +- `[tendermint]` `Hash` is implemented for `tendermint::Time` + ([#1054](https://github.com/informalsystems/tendermint-rs/pull/1054)) +- `[tendermint]` Implement `Clone` for `PrivateKey` + ([#1077](https://github.com/informalsystems/tendermint-rs/issues/1077)) + ## v0.23.0 *Oct 27, 2021* diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b0ae26611..963d88f2c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,75 +1,68 @@ # Contributing -Thank you for your interest in contributing to tendermint-rs. The goal -of tendermint-rs is to provide a high quality, formally verified implementation of -Tendermint. +Thank you for your interest in contributing to tendermint-rs! The goal of +tendermint-rs is to provide a high quality, formally verified interface to +[Tendermint]. -All work on the code base should be motivated by a Github -Issue. Search is a good place 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 you'd like to work on something else, open an Issue to -start the discussion. +This document outlines the best practices for contributing to this repository: -The rest of this document outlines the best practices for contributing to this -repository: - -- [Decision Making](#decision-making) - process for agreeing to changes +- [Proposing Changes](#proposing-changes) - process for agreeing to changes - [Forking](#forking) - fork the repo to make pull requests - [Changelog](#changelog) - changes must be recorded in the changelog - [Pull Requests](#pull-requests) - what makes a good pull request - [Releases](#releases) - how our release process looks -## Decision Making +## Proposing Changes -When contributing to the project, the following process leads to the best chance of -landing the changes in master. +When contributing to the project, adhering to the following guidelines will +dramatically increase the likelihood of changes being accepted quickly. -All new contributions should start with a Github -Issue. The issue helps capture the problem you're trying to solve and allows for -early feedback. Once the issue is created, maintainers may request more detailed -documentation be written in the form of a Request for Comment (RFC) or -Architectural Decision Record -([ADR](https://github.com/informalsystems/tendermint-rs/blob/master/docs/architecture/README.md)). +### Create/locate and assign yourself to an issue -Discussion at the RFC stage will build collective understanding of the dimensions -of the problems and help structure conversations around trade-offs. +1. A good place to start is to search through the [existing + issues](https://github.com/informalsystems/tendermint-rs/issues) for the + problem you're encountering. +2. If no relevant issues exist, submit one describing the *problem* you're + facing, as well as a *definition of done*. A definition of done, which tells + us how to know when the issue can be closed, helps us to scope the problem + and give it definite boundaries. Without a definition of done, issues can + become vague, amorphous changesets that never really come to a satisfactory + conclusion. +3. Once the issue exists, *assign yourself to it*. If there's already someone + assigned to the issue, comment on the issue to ask if you can take it over, + or reach out directly to the current assignee. -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. +### Small PRs -TODO: ADR registration (eg. in an ADR registration issue) +We consider a PR to be "small" if it's under 100 lines' worth of meaningful code +changes, but we will accommodate PRs of up to about 300 lines. Only in +exceptional circumstances will we review larger PRs. -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 master. 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. +Keeping PRs small helps reduce maintainers' workloads, increases speed of +getting feedback, and prevents PRs from standing open for long periods of time. +If you need to make bigger changes, it's recommended that you plan out your +changes in smaller, more manageable chunks (e.g. one issue may take several PRs +to address). -Implementation trajectories should aim to proceed where possible as a series -of smaller incremental changes, in the form of small PRs that can be merged -quickly. This helps manage the load for reviewers and reduces the likelihood -that PRs will sit open for longer. +### ADRs -![Contributing -flow](https://github.com/tendermint/tendermint/blob/v0.33.6/docs/imgs/contributing.png) +If your proposed changes are large, complex, or involve substantial changes to +the architecture of one or more components, a maintainer may ask that you first +submit an [ADR](./docs/architecture/README.md) (architecture decision record) +before you start coding your solution. -Each stage of the process is aimed at creating feedback cycles which align contributors and maintainers to make sure: +ADRs are a way for us to keep track of *why* we've made specific architectural +changes over time. This is intended to help newcomers to the codebase understand +our current architecture and how it has evolved, as well as to help us not +repeat past mistakes. -- Contributors don’t waste their time implementing/proposing features which won’t land in `master`. -- Maintainers have the necessary context in order to support and review contributions. +If you need help with developing an ADR, feel free to ask us. ## Forking -If you do not have write access to the repository, your contribution should be -made through a fork on Github. Fork the repository, contribute to your fork, -and make a pull request back upstream. +If you do not have write access to the repository, your contribution should be +made through a fork on GitHub. Fork the repository, contribute to your fork, and +make a pull request back upstream. When forking, add your fork's URL as a new git remote in your local copy of the repo. For instance, to create a fork and work on a branch of it: @@ -77,10 +70,12 @@ repo. For instance, to create a fork and work on a branch of it: - Create the fork on GitHub, using the fork button. - `cd` to the original clone of the repo on your machine - `git remote rename origin upstream` -- `git remote add origin git@github.com: +- `git remote add origin git@github.com:` Now `origin` refers to your fork and `upstream` refers to this version. -Now `git push -u origin master` to update the fork, and make pull requests against this repo. + +`git push -u origin master` to update the fork, and make pull requests against +this repo. To pull in updates from the origin repo, run @@ -91,48 +86,43 @@ To pull in updates from the origin repo, run Every non-trivial PR must update the [CHANGELOG.md]. This is accomplished indirectly by adding entries to the `.changelog` folder in [unclog][unclog] -format. `CHANGELOG.md` will be built by whomever is responsible for performing -a release just prior to release - this is to avoid changelog conflicts prior to +format. `CHANGELOG.md` will be built by whomever is responsible for performing a +release just prior to release - this is to avoid changelog conflicts prior to releases. -The Changelog is *not* a record of what Pull Requests were merged; -the commit history already shows that. The Changelog is a notice to the user -about how their expectations of the software should be modified. -It is part of the UX of a release and is a *critical* user facing integration point. -The Changelog must be clean, inviting, and readable, with concise, meaningful entries. -Entries must be semantically meaningful to users. If a change takes multiple -Pull Requests to complete, it should likely have only a single entry in the -Changelog describing the net effect to the user. +The Changelog is *not* a record of which pull requests were merged; the commit +history already shows that. The Changelog is a notice to the user about how +their expectations of the software should be modified. It is part of the UX of +a release and is a *critical* user facing integration point. The Changelog must +be clean, inviting, and readable, with concise, meaningful entries. Entries +must be semantically meaningful to users. If a change takes multiple Pull +Requests to complete, it should likely have only a single entry in the Changelog +describing the net effect to the user. When writing Changelog entries, ensure they are targeting users of the software, not fellow developers. Developers have much more context and care about more -things than users do. Changelogs are for users. +things than users do. Changelogs are for users. -Changelog structure is modeled after -[Tendermint -Core](https://github.com/tendermint/tendermint/blob/master/CHANGELOG.md) -and +Changelog structure is modeled after [Tendermint +Core](https://github.com/tendermint/tendermint/blob/master/CHANGELOG.md) and [Hashicorp Consul](http://github.com/hashicorp/consul/tree/master/CHANGELOG.md). See those changelogs for examples. -Changes for a given release should be split between the five sections: Security, Breaking -Changes, Features, Improvements, Bug Fixes. +Changes for a given release should be split between the five sections: Security, +Breaking Changes, Features, Improvements, Bug Fixes. Changelog entries should be formatted as follows: + ``` -- [pkg] \#xxx Some description about the change (@contributor) +- `[pkg]` A description of the change with *users* in mind + ([#xxx](https://github.com/informalsystems/tendermint-rs/issues/xxx)) ``` -Here, `pkg` is the part of the code that changed (typically a -top-level crate, but could be /), `xxx` is the pull-request number, and `contributor` -is the author/s of the change. -It's also acceptable for `xxx` to refer to the relevent 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. +Here, `pkg` is the part of the code that changed, and `xxx` is the issue or +pull request number. -Changelog entries should be ordered alphabetically according to the -`pkg`, and numerically according to the pull-request number. +Changelog entries should be ordered alphabetically according to the `pkg`, and +numerically according to the issue/pull-request number. Changes with multiple classifications should be doubly included (eg. a bug fix that is also a breaking change should be recorded under both). @@ -140,16 +130,24 @@ that is also a breaking change should be recorded under both). Breaking changes are further subdivided according to the APIs/users they impact. Any change that effects multiple APIs/users should be recorded multiply - for instance, a change to some core protocol data structure might need to be -reflected both as breaking the core protocol but also breaking any APIs where core data structures are -exposed. +reflected both as breaking the core protocol but also breaking any APIs where +core data structures are exposed. ## Pull Requests -The master development branch is `master`. -Branch names should be prefixed with the author, eg. `name/feature-x`. +Pull requests are squash-merged into one of the following primary development +branches: + +- `master` - targeting compatibility with the [latest official release of + Tendermint](https://github.com/tendermint/tendermint/releases). +- tendermint-rs version-specific branches, e.g. `v0.23.x` - targeting patches to + older versions of tendermint-rs. -Pull requests are made against `master` -and are squash merged into master. +Indicate in your pull request which version of Tendermint/tendermint-rs you are +targeting with your changes. Changes to multiple versions will require separate +PRs. See the [README](./README.md#versioning) for the version support matrix. + +Branch names should be prefixed with the author, eg. `name/feature-x`. PRs must: @@ -157,10 +155,17 @@ PRs must: - update any relevant documentation and include tests. - update the [changelog](#changelog) with a description of the change -Pull requests should aim to be small and self contained to facilitate quick -review and merging. Larger change sets should be broken up across multiple PRs. -Commits should be concise but informative, and moderately clean. Commits will be squashed into a -single commit for the PR with all the commit messages. +Commits should be concise but informative, and moderately clean. Commits will be +squashed into a single commit for the PR with all the commit messages. + +### Draft PRs + +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 master. 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. Maintainers will not review draft PRs. ## Releases @@ -172,8 +177,8 @@ Our release process is as follows: in this release. 2. Running `unclog build > CHANGELOG.md` to update the changelog. 3. Committing this updated `CHANGELOG.md` file to the repo. -2. Push this to a branch `release/vX.Y.Z` according to the version number of - the anticipated release (e.g. `release/v0.17.0`) and open a **draft PR**. +2. Push this to a branch `release/vX.Y.Z` according to the version number of the + anticipated release (e.g. `release/v0.17.0`) and open a **draft PR**. 3. Bump all relevant versions in the codebase to the new version and push these changes to the release PR. This includes: 1. All `Cargo.toml` files (making sure dependencies' versions are updated @@ -184,13 +189,14 @@ Our release process is as follows: documentation compiles and seems up-to-date and coherent. Fix any potential issues here and push them to the release PR. 5. Mark the PR as **Ready for Review** and incorporate feedback on the release. -6. Once approved, run the [`release.sh`] script. Fix any problems that may - arise during this process and push the changes to the release PR. - This step requires the appropriate privileges to push crates to [crates.io]. -7. Once all crates have been successfully released, merge the PR to `master` - and tag the repo at the new version (e.g. `v0.17.0`). +6. Once approved, run the [`release.sh`] script. Fix any problems that may arise + during this process and push the changes to the release PR. This step + requires the appropriate privileges to push crates to [crates.io]. +7. Once all crates have been successfully released, merge the PR to `master` and + tag the repo at the new version (e.g. `v0.17.0`). [CHANGELOG.md]: https://github.com/informalsystems/tendermint-rs/blob/master/CHANGELOG.md [`release.sh`]: https://github.com/informalsystems/tendermint-rs/blob/master/release.sh [crates.io]: https://crates.io [unclog]: https://github.com/informalsystems/unclog +[Tendermint]: https://tendermint.com diff --git a/Cargo.toml b/Cargo.toml index 6411b720b..d5fa707d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,8 +5,10 @@ members = [ "config", "light-client", "light-client-js", + "light-client-verifier", "p2p", "pbt-gen", + "privval", "proto", "rpc", "std-ext", @@ -16,7 +18,8 @@ members = [ ] exclude = [ - "proto-compiler" + "proto-compiler", + "tools/no-std-check" ] [profile.release.package.tendermint-light-client-js] diff --git a/README.md b/README.md index 98f052ec5..2697b7e4a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# tendermint.rs +# tendermint-rs [![Crate][crate-image]][crate-link] [![Docs][docs-image]][docs-link] @@ -9,14 +9,39 @@ [Tendermint] in Rust with [TLA+ specifications](/docs/spec). -Tendermint is a high-performance blockchain consensus engine -for Byzantine fault tolerant applications written in any programming language. +Tendermint is a high-performance blockchain consensus engine for Byzantine fault +tolerant applications written in any programming language. ## Requirements Tested against the latest stable version of Rust. May work with older versions. -Compatible with the v0.34 series of [Tendermint Core][Tendermint]. +## Versioning + +Each of the following branches targets a specific version of [Tendermint +Core][Tendermint]: + +| tendermint-rs branch | tendermint-rs version | Tendermint version | +| -------------------- | --------------------- | ------------------ | +| `master` | v0.24.x | v0.35.x | +| `v0.23.x` | v0.23.x | v0.34.x | + +We will do our best to support one version behind the latest official release of +Tendermint Core (e.g. if v0.35.x is the latest release, we will aim to support +v0.34.x as well). + +### Semantic Versioning + +We do our best to follow [Semantic Versioning](https://semver.org/). However, as +we are pre-v1.0.0, we use the MINOR version to refer to breaking changes and the +PATCH version for features, improvements, and fixes. + +We use the same version for all crates and release them collectively. + +If you are using the v0.23.x series of tendermint-rs, however, **please pin your +dependencies to a specific patch version**. We may need to introduce breaking +changes to this series in patches (e.g. if critical security updates require +it), but we will do our best to avoid doing so. ## Documentation @@ -24,43 +49,38 @@ See each component for the relevant documentation. Libraries: -- [tendermint](./tendermint) - Tendermint data structures and - serialization -- [tendermint-rpc](./rpc) - Tendermint RPC client and - response types -- [light-client](./light-client) - Tendermint light client library for verifying - signed headers, tracking validator set changes, and detecting forks +- [tendermint](./tendermint) - Tendermint data structures and serialization +- [tendermint-abci](./abci) - A lightweight, low-level framework for building + Tendermint ABCI applications in Rust +- [tendermint-light-client](./light-client) - Tendermint light client library + for verifying signed headers, tracking validator set changes, and detecting + forks +- [tendermint-light-client-js](./light-client-js) - Low-level WASM interface for + interacting with the Tendermint light client verification functionality +- [tendermint-p2p](./p2p) - At present this primarily provides the ability to + connect to Tendermint nodes via Tendermint's [secret + connection](tendermint-secret-conn). +- [tendermint-proto](./proto) - Protobuf data structures (generated using Prost) + for wire-level interaction with Tendermint +- [tendermint-rpc](./rpc) - Tendermint RPC client and response types ## Releases -Release tags can be found on [Github](https://github.com/informalsystems/tendermint-rs/releases). +Release tags can be found on +[GitHub](https://github.com/informalsystems/tendermint-rs/releases). -Crates are released on crates.io. +Crates are released on [crates.io](https://crates.io). ## Contributing -The Tendermint protocols are specified in English in the -[tendermint/spec repo](https://github.com/tendermint/spec). -Any protocol changes or clarifications should be contributed there. +The Tendermint protocols are specified in English in the [tendermint/tendermint +repo](https://github.com/tendermint/tendermint/tree/master/spec). Any protocol +changes or clarifications should be contributed there. -This repo contains the TLA+ specifications and Rust implementations for -various components of Tendermint. See the [CONTRIBUTING.md][contributing] to start +This repo contains the TLA+ specifications and Rust implementations for various +components of Tendermint. See the [CONTRIBUTING.md][contributing] to start contributing. -## Versioning - -We follow [Semantic Versioning](https://semver.org/). However, as we are -pre-v1.0.0, we use the MINOR version to refer to breaking changes and the PATCH -version for features, improvements, and fixes. - -Only the following crates are covered by SemVer guarantees: - -- tendermint -- tendermint-rpc - -Other crates may change arbitrarily with every release for now. - -We use the same version for all crates and release them collectively. ## Resources @@ -111,4 +131,5 @@ limitations under the License. [tendermint-rpc-docs-link]: https://docs.rs/tendermint-rpc/ [Tendermint]: https://github.com/tendermint/tendermint [tendermint-light-client-docs-link]: https://docs.rs/tendermint-light-client/ +[tendermint-secret-conn]: https://docs.tendermint.com/master/spec/p2p/peer.html#authenticated-encryption-handshake [contributing]: ./CONTRIBUTING.md diff --git a/abci/Cargo.toml b/abci/Cargo.toml index aaf224b45..cf29b8490 100644 --- a/abci/Cargo.toml +++ b/abci/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tendermint-abci" -version = "0.23.0" +version = "0.24.0-pre.2" authors = ["Informal Systems "] edition = "2018" license = "Apache-2.0" @@ -32,8 +32,8 @@ binary = [ [dependencies] bytes = { version = "1.0", default-features = false } -prost = { version = "0.9", default-features = false } -tendermint-proto = { version = "0.23.0", default-features = false, path = "../proto" } +prost = { version = "0.10", default-features = false } +tendermint-proto = { version = "0.24.0-pre.2", default-features = false, path = "../proto" } tracing = { version = "0.1", default-features = false } flex-error = { version = "0.4.4", default-features = false } structopt = { version = "0.3", optional = true, default-features = false } diff --git a/abci/src/application.rs b/abci/src/application.rs index b4a848608..10bec07d9 100644 --- a/abci/src/application.rs +++ b/abci/src/application.rs @@ -5,15 +5,14 @@ pub mod echo; #[cfg(feature = "kvstore-app")] pub mod kvstore; -use tendermint_proto::abci::request::Value; use tendermint_proto::abci::{ - response, Request, RequestApplySnapshotChunk, RequestBeginBlock, RequestCheckTx, - RequestDeliverTx, RequestEcho, RequestEndBlock, RequestInfo, RequestInitChain, - RequestLoadSnapshotChunk, RequestOfferSnapshot, RequestQuery, RequestSetOption, Response, + request::Value, response, Request, RequestApplySnapshotChunk, RequestBeginBlock, + RequestCheckTx, RequestDeliverTx, RequestEcho, RequestEndBlock, RequestInfo, RequestInitChain, + RequestLoadSnapshotChunk, RequestOfferSnapshot, RequestQuery, Response, ResponseApplySnapshotChunk, ResponseBeginBlock, ResponseCheckTx, ResponseCommit, ResponseDeliverTx, ResponseEcho, ResponseEndBlock, ResponseFlush, ResponseInfo, ResponseInitChain, ResponseListSnapshots, ResponseLoadSnapshotChunk, ResponseOfferSnapshot, - ResponseQuery, ResponseSetOption, + ResponseQuery, }; /// An ABCI application. @@ -77,12 +76,6 @@ pub trait Application: Send + Clone + 'static { Default::default() } - /// Allows the Tendermint node to request that the application set an - /// option to a particular value. - fn set_option(&self, _request: RequestSetOption) -> ResponseSetOption { - Default::default() - } - /// Used during state sync to discover available snapshots on peers. fn list_snapshots(&self) -> ResponseListSnapshots { Default::default() @@ -124,7 +117,6 @@ impl RequestDispatcher for A { Value::Echo(req) => response::Value::Echo(self.echo(req)), Value::Flush(_) => response::Value::Flush(self.flush()), Value::Info(req) => response::Value::Info(self.info(req)), - Value::SetOption(req) => response::Value::SetOption(self.set_option(req)), Value::InitChain(req) => response::Value::InitChain(self.init_chain(req)), Value::Query(req) => response::Value::Query(self.query(req)), Value::BeginBlock(req) => response::Value::BeginBlock(self.begin_block(req)), @@ -135,13 +127,13 @@ impl RequestDispatcher for A { Value::ListSnapshots(_) => response::Value::ListSnapshots(self.list_snapshots()), Value::OfferSnapshot(req) => { response::Value::OfferSnapshot(self.offer_snapshot(req)) - } + }, Value::LoadSnapshotChunk(req) => { response::Value::LoadSnapshotChunk(self.load_snapshot_chunk(req)) - } + }, Value::ApplySnapshotChunk(req) => { response::Value::ApplySnapshotChunk(self.apply_snapshot_chunk(req)) - } + }, }), } } diff --git a/abci/src/application/echo.rs b/abci/src/application/echo.rs index 825c2d8f0..93e7fd5cf 100644 --- a/abci/src/application/echo.rs +++ b/abci/src/application/echo.rs @@ -3,13 +3,7 @@ use crate::Application; /// Trivial echo application, mainly for testing purposes. -#[derive(Clone)] +#[derive(Clone, Default)] pub struct EchoApp; -impl Default for EchoApp { - fn default() -> Self { - Self {} - } -} - impl Application for EchoApp {} diff --git a/abci/src/application/kvstore.rs b/abci/src/application/kvstore.rs index 57a687345..1a68cb142 100644 --- a/abci/src/application/kvstore.rs +++ b/abci/src/application/kvstore.rs @@ -1,16 +1,19 @@ //! In-memory key/value store ABCI application. -use crate::codec::{encode_varint, MAX_VARINT_LENGTH}; -use crate::{Application, Error}; +use std::{ + collections::HashMap, + sync::mpsc::{channel, Receiver, Sender}, +}; + use bytes::BytesMut; -use std::collections::HashMap; -use std::sync::mpsc::{channel, Receiver, Sender}; use tendermint_proto::abci::{ Event, EventAttribute, RequestCheckTx, RequestDeliverTx, RequestInfo, RequestQuery, ResponseCheckTx, ResponseCommit, ResponseDeliverTx, ResponseInfo, ResponseQuery, }; use tracing::{debug, info}; +use crate::{codec::MAX_VARINT_LENGTH, Application, Error}; + /// In-memory, hashmap-backed key/value store ABCI application. /// /// This structure effectively just serves as a handle to the actual key/value @@ -44,7 +47,7 @@ use tracing::{debug, info}; /// // Deliver a transaction and then commit the transaction /// client /// .deliver_tx(RequestDeliverTx { -/// tx: "test-key=test-value".as_bytes().to_owned(), +/// tx: "test-key=test-value".into(), /// }) /// .unwrap(); /// client.commit().unwrap(); @@ -52,7 +55,7 @@ use tracing::{debug, info}; /// // We should be able to query for the data we just delivered above /// let res = client /// .query(RequestQuery { -/// data: "test-key".as_bytes().to_owned(), +/// data: "test-key".into(), /// path: "".to_string(), /// height: 0, /// prove: false, @@ -123,17 +126,17 @@ impl Application for KeyValueStoreApp { version: "0.1.0".to_string(), app_version: 1, last_block_height, - last_block_app_hash, + last_block_app_hash: last_block_app_hash.into(), } } fn query(&self, request: RequestQuery) -> ResponseQuery { - let key = match String::from_utf8(request.data.clone()) { + let key = match std::str::from_utf8(&request.data) { Ok(s) => s, Err(e) => panic!("Failed to intepret key as UTF-8: {}", e), }; debug!("Attempting to get key: {}", key); - match self.get(key.clone()) { + match self.get(key) { Ok((height, value_opt)) => match value_opt { Some(value) => ResponseQuery { code: 0, @@ -141,7 +144,7 @@ impl Application for KeyValueStoreApp { info: "".to_string(), index: 0, key: request.data, - value: value.into_bytes(), + value: value.into_bytes().into(), proof_ops: None, height, codespace: "".to_string(), @@ -152,7 +155,7 @@ impl Application for KeyValueStoreApp { info: "".to_string(), index: 0, key: request.data, - value: vec![], + value: Default::default(), proof_ops: None, height, codespace: "".to_string(), @@ -165,28 +168,31 @@ impl Application for KeyValueStoreApp { fn check_tx(&self, _request: RequestCheckTx) -> ResponseCheckTx { ResponseCheckTx { code: 0, - data: vec![], + data: Default::default(), log: "".to_string(), info: "".to_string(), gas_wanted: 1, gas_used: 0, events: vec![], codespace: "".to_string(), + mempool_error: "".to_string(), + priority: 0, + sender: "".to_string(), } } fn deliver_tx(&self, request: RequestDeliverTx) -> ResponseDeliverTx { - let tx = String::from_utf8(request.tx).unwrap(); + let tx = std::str::from_utf8(&request.tx).unwrap(); let tx_parts = tx.split('=').collect::>(); let (key, value) = if tx_parts.len() == 2 { (tx_parts[0], tx_parts[1]) } else { - (tx.as_ref(), tx.as_ref()) + (tx, tx) }; let _ = self.set(key, value).unwrap(); ResponseDeliverTx { code: 0, - data: vec![], + data: Default::default(), log: "".to_string(), info: "".to_string(), gas_wanted: 0, @@ -195,18 +201,18 @@ impl Application for KeyValueStoreApp { r#type: "app".to_string(), attributes: vec![ EventAttribute { - key: "key".as_bytes().to_owned(), - value: key.as_bytes().to_owned(), + key: "key".to_string(), + value: key.to_string(), index: true, }, EventAttribute { - key: "index_key".as_bytes().to_owned(), - value: "index is working".as_bytes().to_owned(), + key: "index_key".to_string(), + value: "index is working".to_string(), index: true, }, EventAttribute { - key: "noindex_key".as_bytes().to_owned(), - value: "index is working".as_bytes().to_owned(), + key: "noindex_key".to_string(), + value: "index is working".to_string(), index: false, }, ], @@ -221,7 +227,7 @@ impl Application for KeyValueStoreApp { let (height, app_hash) = channel_recv(&result_rx).unwrap(); info!("Committed height {}", height); ResponseCommit { - data: app_hash, + data: app_hash.into(), retain_height: height - 1, } } @@ -253,14 +259,14 @@ impl KeyValueStoreDriver { match cmd { Command::GetInfo { result_tx } => { channel_send(&result_tx, (self.height, self.app_hash.clone()))? - } + }, Command::Get { key, result_tx } => { debug!("Getting value for \"{}\"", key); channel_send( &result_tx, (self.height, self.store.get(&key).map(Clone::clone)), )?; - } + }, Command::Set { key, value, @@ -268,7 +274,7 @@ impl KeyValueStoreDriver { } => { debug!("Setting \"{}\" = \"{}\"", key, value); channel_send(&result_tx, self.store.insert(key, value))?; - } + }, Command::Commit { result_tx } => self.commit(result_tx)?, } } @@ -278,7 +284,7 @@ impl KeyValueStoreDriver { // As in the Go-based key/value store, simply encode the number of // items as the "app hash" let mut app_hash = BytesMut::with_capacity(MAX_VARINT_LENGTH); - encode_varint(self.store.len() as u64, &mut app_hash); + prost::encoding::encode_varint(self.store.len() as u64, &mut app_hash); self.app_hash = app_hash.to_vec(); self.height += 1; channel_send(&result_tx, (self.height, self.app_hash.clone())) diff --git a/abci/src/client.rs b/abci/src/client.rs index c5146f88a..a7a82be44 100644 --- a/abci/src/client.rs +++ b/abci/src/client.rs @@ -1,18 +1,18 @@ //! Blocking ABCI client. -use crate::codec::ClientCodec; -use crate::Error; use std::net::{TcpStream, ToSocketAddrs}; + use tendermint_proto::abci::{ - request, response, RequestApplySnapshotChunk, RequestBeginBlock, RequestCheckTx, RequestCommit, - RequestDeliverTx, RequestEndBlock, RequestFlush, RequestInfo, RequestInitChain, - RequestListSnapshots, RequestLoadSnapshotChunk, RequestOfferSnapshot, RequestQuery, - RequestSetOption, ResponseApplySnapshotChunk, ResponseBeginBlock, ResponseCheckTx, - ResponseCommit, ResponseDeliverTx, ResponseEndBlock, ResponseFlush, ResponseInfo, + request, response, Request, RequestApplySnapshotChunk, RequestBeginBlock, RequestCheckTx, + RequestCommit, RequestDeliverTx, RequestEcho, RequestEndBlock, RequestFlush, RequestInfo, + RequestInitChain, RequestListSnapshots, RequestLoadSnapshotChunk, RequestOfferSnapshot, + RequestQuery, ResponseApplySnapshotChunk, ResponseBeginBlock, ResponseCheckTx, ResponseCommit, + ResponseDeliverTx, ResponseEcho, ResponseEndBlock, ResponseFlush, ResponseInfo, ResponseInitChain, ResponseListSnapshots, ResponseLoadSnapshotChunk, ResponseOfferSnapshot, - ResponseQuery, ResponseSetOption, + ResponseQuery, }; -use tendermint_proto::abci::{Request, RequestEcho, ResponseEcho}; + +use crate::{codec::ClientCodec, Error}; /// The size of the read buffer for the client in its receiving of responses /// from the server. @@ -58,7 +58,7 @@ macro_rules! perform { response::Value::$type(r) => Ok(r), r => { Err(Error::unexpected_server_response_type(stringify!($type).to_string(), r).into()) - } + }, } }; } @@ -113,11 +113,6 @@ impl Client { perform!(self, Commit, RequestCommit {}) } - /// Request that the application set an option to a particular value. - pub fn set_option(&mut self, req: RequestSetOption) -> Result { - perform!(self, SetOption, req) - } - /// Used during state sync to discover available snapshots on peers. pub fn list_snapshots(&mut self) -> Result { perform!(self, ListSnapshots, RequestListSnapshots {}) diff --git a/abci/src/codec.rs b/abci/src/codec.rs index 170d384e6..67ddfbe74 100644 --- a/abci/src/codec.rs +++ b/abci/src/codec.rs @@ -4,10 +4,13 @@ //! //! [tsp]: https://docs.tendermint.com/master/spec/abci/client-server.html#tsp +use std::{ + io::{Read, Write}, + marker::PhantomData, +}; + use bytes::{Buf, BufMut, BytesMut}; use prost::Message; -use std::io::{Read, Write}; -use std::marker::PhantomData; use tendermint_proto::abci::{Request, Response}; use crate::error::Error; @@ -127,7 +130,7 @@ where message.encode(&mut buf).map_err(Error::encode)?; let buf = buf.freeze(); - encode_varint(buf.len() as u64, &mut dst); + prost::encoding::encode_varint(buf.len() as u64, &mut dst); dst.put(buf); Ok(()) } @@ -139,11 +142,11 @@ where { let src_len = src.len(); let mut tmp = src.clone().freeze(); - let encoded_len = match decode_varint(&mut tmp) { + let encoded_len = match prost::encoding::decode_varint(&mut tmp) { Ok(len) => len, // We've potentially only received a partial length delimiter Err(_) if src_len <= MAX_VARINT_LENGTH => return Ok(None), - Err(e) => return Err(e), + Err(e) => return Err(Error::decode(e)), }; let remaining = tmp.remaining() as u64; if remaining < encoded_len { @@ -161,14 +164,3 @@ where Ok(Some(res)) } } - -// encode_varint and decode_varint will be removed once -// https://github.com/tendermint/tendermint/issues/5783 lands in Tendermint. -pub fn encode_varint(val: u64, mut buf: &mut B) { - prost::encoding::encode_varint(val << 1, &mut buf); -} - -pub fn decode_varint(mut buf: &mut B) -> Result { - let len = prost::encoding::decode_varint(&mut buf).map_err(Error::decode)?; - Ok(len >> 1) -} diff --git a/abci/src/lib.rs b/abci/src/lib.rs index 8ec63a960..20a660c2f 100644 --- a/abci/src/lib.rs +++ b/abci/src/lib.rs @@ -10,14 +10,13 @@ pub mod error; mod server; // Common exports -pub use application::Application; -#[cfg(feature = "client")] -pub use client::{Client, ClientBuilder}; -pub use error::Error; -pub use server::{Server, ServerBuilder}; - // Example applications #[cfg(feature = "echo-app")] pub use application::echo::EchoApp; #[cfg(feature = "kvstore-app")] pub use application::kvstore::{KeyValueStoreApp, KeyValueStoreDriver}; +pub use application::Application; +#[cfg(feature = "client")] +pub use client::{Client, ClientBuilder}; +pub use error::Error; +pub use server::{Server, ServerBuilder}; diff --git a/abci/src/server.rs b/abci/src/server.rs index 623143307..3f822945a 100644 --- a/abci/src/server.rs +++ b/abci/src/server.rs @@ -1,12 +1,14 @@ //! ABCI application server interface. -use crate::application::RequestDispatcher; -use crate::codec::ServerCodec; -use crate::{error::Error, Application}; -use std::net::{TcpListener, TcpStream, ToSocketAddrs}; -use std::thread; +use std::{ + net::{TcpListener, TcpStream, ToSocketAddrs}, + thread, +}; + use tracing::{error, info}; +use crate::{application::RequestDispatcher, codec::ServerCodec, error::Error, Application}; + /// The size of the read buffer for each incoming connection to the ABCI /// server (1MB). pub const DEFAULT_SERVER_READ_BUF_SIZE: usize = 1024 * 1024; @@ -104,12 +106,12 @@ impl Server { addr, e ); return; - } + }, }, None => { info!("Client {} terminated stream", addr); return; - } + }, }; let response = app.handle(request); if let Err(e) = codec.send(response) { diff --git a/abci/tests/kvstore_app.rs b/abci/tests/kvstore_app.rs index 62a1c51d6..05c821483 100644 --- a/abci/tests/kvstore_app.rs +++ b/abci/tests/kvstore_app.rs @@ -3,6 +3,7 @@ #[cfg(all(feature = "client", feature = "kvstore-app"))] mod kvstore_app_integration { use std::thread; + use tendermint_abci::{ClientBuilder, KeyValueStoreApp, ServerBuilder}; use tendermint_proto::abci::{RequestDeliverTx, RequestEcho, RequestQuery}; @@ -24,19 +25,19 @@ mod kvstore_app_integration { client .deliver_tx(RequestDeliverTx { - tx: "test-key=test-value".as_bytes().to_owned(), + tx: "test-key=test-value".into(), }) .unwrap(); client.commit().unwrap(); let res = client .query(RequestQuery { - data: "test-key".as_bytes().to_owned(), + data: "test-key".into(), path: "".to_string(), height: 0, prove: false, }) .unwrap(); - assert_eq!(res.value, "test-value".as_bytes().to_owned()); + assert_eq!(res.value, "test-value".as_bytes()); } } diff --git a/config/Cargo.toml b/config/Cargo.toml index 3c7a4cf37..87a2aed7e 100644 --- a/config/Cargo.toml +++ b/config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tendermint-config" -version = "0.23.0" # Also update `html_root_url` in lib.rs and +version = "0.24.0-pre.2" # Also update `html_root_url` in lib.rs and # depending crates (rpc, light-node, ..) when bumping this license = "Apache-2.0" homepage = "https://www.tendermint.com/" @@ -24,11 +24,8 @@ authors = [ all-features = true rustdoc-args = ["--cfg", "docsrs"] -[lib] -crate-type = ["cdylib", "rlib"] - [dependencies] -tendermint = { version = "0.23.0", default-features = false, path = "../tendermint" } +tendermint = { version = "0.24.0-pre.2", default-features = false, path = "../tendermint" } flex-error = { version = "0.4.4", default-features = false } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/config/src/config.rs b/config/src/config.rs index 5f254046d..2c93672c6 100644 --- a/config/src/config.rs +++ b/config/src/config.rs @@ -6,20 +6,30 @@ //! - `node_key.rs`: `config::node_key::NodeKey` //! - `priv_validator_key.rs`: `config::priv_validator_key::PrivValidatorKey` -use crate::net; -use crate::node_key::NodeKey; -use crate::Error; - -use crate::prelude::*; use alloc::collections::{btree_map, BTreeMap}; use core::{fmt, str::FromStr}; +use std::{ + fs, + path::{Path, PathBuf}, +}; + use serde::{de, de::Error as _, ser, Deserialize, Serialize}; -use std::fs; -use std::path::{Path, PathBuf}; use tendermint::{genesis::Genesis, node, Moniker, Timeout}; +use crate::{ + net, + node_key::NodeKey, + prelude::*, + serialization::{ + deserialize_comma_separated_list, deserialize_from_str, deserialize_optional_value, + serialize_comma_separated_list, serialize_optional_value, serialize_to_str, + }, + Error, +}; + /// Tendermint `config.toml` file #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] pub struct TendermintConfig { /// TCP or UNIX socket address of the ABCI application, /// or the name of an ABCI application compiled in with the Tendermint binary. @@ -28,10 +38,17 @@ pub struct TendermintConfig { /// A custom human readable name for this node pub moniker: Moniker, - /// If this node is many blocks behind the tip of the chain, FastSync - /// allows them to catchup quickly by downloading blocks in parallel - /// and verifying their commits - pub fast_sync: bool, + /// Mode of Node: full | validator | seed + /// * validator node + /// - all reactors + /// - with priv_validator_key.json, priv_validator_state.json + /// * full node + /// - all reactors + /// - No priv_validator_key.json, priv_validator_state.json + /// * seed node + /// - only P2P, PEX Reactor + /// - No priv_validator_key.json, priv_validator_state.json + pub mode: NodeMode, /// Database backend: `goleveldb | cleveldb | boltdb | rocksdb | badgerdb` pub db_backend: DbBackend, @@ -48,23 +65,8 @@ pub struct TendermintConfig { /// Path to the JSON file containing the initial validator set and other meta data pub genesis_file: PathBuf, - /// Path to the JSON file containing the private key to use as a validator in the consensus - /// protocol - pub priv_validator_key_file: Option, - - /// Path to the JSON file containing the last sign state of a validator - pub priv_validator_state_file: PathBuf, - - /// TCP or UNIX socket address for Tendermint to listen on for - /// connections from an external PrivValidator process - #[serde( - deserialize_with = "deserialize_optional_value", - serialize_with = "serialize_optional_value" - )] - pub priv_validator_laddr: Option, - - /// Path to the JSON file containing the private key to use for node authentication in the p2p - /// protocol + /// Path to the JSON file containing the private key to use for node + /// authentication in the p2p protocol pub node_key_file: PathBuf, /// Mechanism to connect to the ABCI application: socket | grpc @@ -74,6 +76,9 @@ pub struct TendermintConfig { /// so the app can decide if we should keep the connection or not pub filter_peers: bool, + /// Private validator configuration options + pub priv_validator: PrivValidatorConfig, + /// rpc server configuration options pub rpc: RpcConfig, @@ -95,8 +100,8 @@ pub struct TendermintConfig { /// statesync configuration options pub statesync: StatesyncConfig, - /// fastsync configuration options - pub fastsync: FastsyncConfig, + /// blocksync configuration options + pub blocksync: BlocksyncConfig, } impl TendermintConfig { @@ -136,6 +141,67 @@ impl TendermintConfig { } } +/// The mode in which a node is to be started. +#[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +pub enum NodeMode { + /// Validator node: + /// - all reactors + /// - with priv_validator_key.json, priv_validator_state.json + #[serde(rename = "validator")] + Validator, + + /// Full node: + /// - all reactors + /// - No priv_validator_key.json, priv_validator_state.json + #[serde(rename = "full")] + Full, + + /// Seed node: + /// - only P2P, PEX Reactor + /// - No priv_validator_key.json, priv_validator_state.json + #[serde(rename = "seed")] + Seed, +} + +impl Default for NodeMode { + fn default() -> Self { + Self::Validator + } +} + +/// Private validator configuration options +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub struct PrivValidatorConfig { + /// Path to the JSON file containing the private key to use as a validator + /// in the consensus protocol + pub key_file: PathBuf, + + /// Path to the JSON file containing the last sign state of a validator + pub state_file: PathBuf, + + /// TCP or UNIX socket address for Tendermint to listen on for connections + /// from an external PrivValidator process when the listenAddr is prefixed + /// with grpc instead of tcp it will use the gRPC Client + #[serde( + deserialize_with = "deserialize_optional_value", + serialize_with = "serialize_optional_value" + )] + pub laddr: Option, + + /// Path to the client certificate generated while creating needed files for + /// secure connection. If a remote validator address is provided but no + /// certificate, the connection will be insecure + pub client_certificate_file: PathBuf, + + /// Client key generated while creating certificates for secure connection + pub client_key_file: PathBuf, + + /// Path to the Root Certificate Authority used to sign both client and + /// server certificates + pub root_ca_file: PathBuf, +} + /// Database backend #[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub enum DbBackend { @@ -176,7 +242,7 @@ impl LogLevel { { self.components .get(key.as_ref()) - .or_else(|| self.global.as_ref()) + .or(self.global.as_ref()) .map(AsRef::as_ref) } @@ -280,6 +346,7 @@ pub enum AbciMode { /// Tendermint `config.toml` file's `[rpc]` section #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] pub struct RpcConfig { /// TCP or UNIX socket address for the RPC server to listen on pub laddr: net::Address, @@ -297,17 +364,21 @@ pub struct RpcConfig { /// TCP or UNIX socket address for the gRPC server to listen on /// NOTE: This server only supports `/broadcast_tx_commit` + /// Deprecated gRPC in the RPC layer of Tendermint will be deprecated in + /// 0.36. #[serde( deserialize_with = "deserialize_optional_value", serialize_with = "serialize_optional_value" )] pub grpc_laddr: Option, - /// Maximum number of simultaneous GRPC connections. - /// Does not include RPC (HTTP&WebSocket) connections. See `max_open_connections`. + /// Maximum number of simultaneous GRPC connections. Does not include RPC + /// (HTTP&WebSocket) connections. See `max_open_connections`. + /// Deprecated gRPC in the RPC layer of Tendermint will be deprecated in + /// 0.36. pub grpc_max_open_connections: u64, - /// Activate unsafe RPC commands like `/dial_seeds` and `/unsafe_flush_mempool` + /// Activate unsafe RPC commands like /dial-seeds and /unsafe-flush-mempool #[serde(rename = "unsafe")] pub unsafe_commands: bool, @@ -405,27 +476,43 @@ impl fmt::Display for CorsHeader { /// peer to peer configuration options #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] pub struct P2PConfig { + /// Enable the legacy p2p layer. + pub use_legacy: bool, + + /// Select the p2p internal queue + pub queue_type: P2PQueueType, + /// Address to listen for incoming connections pub laddr: net::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 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 or use UPnP + /// to figure out the address. IP and port are required. #[serde( deserialize_with = "deserialize_optional_value", serialize_with = "serialize_optional_value" )] pub external_address: Option, - /// Comma separated list of seed nodes to connect to + /// Comma separated list of seed nodes to connect to. We only use these if + /// we can’t connect to peers in the addrbook. #[serde( serialize_with = "serialize_comma_separated_list", deserialize_with = "deserialize_comma_separated_list" )] pub seeds: Vec, + /// Comma separated list of peers to be added to the peer store on startup. + /// Either `bootstrap_peers` or `persistent_peers` are needed for peer + /// discovery + #[serde( + serialize_with = "serialize_comma_separated_list", + deserialize_with = "deserialize_comma_separated_list" + )] + pub bootstrap_peers: Vec, + /// Comma separated list of nodes to keep persistent connections to #[serde( serialize_with = "serialize_comma_separated_list", @@ -436,19 +523,22 @@ pub struct P2PConfig { /// UPNP port forwarding pub upnp: bool, - /// Path to address book + /// Path to address book. pub addr_book_file: PathBuf, /// Set `true` for strict address routability rules /// Set `false` for private or local networks pub addr_book_strict: bool, - /// Maximum number of inbound peers + /// Maximum number of inbound peers. pub max_num_inbound_peers: u64, /// Maximum number of outbound peers to connect to, excluding persistent peers pub max_num_outbound_peers: u64, + /// Maximum number of connections (inbound and outbound). + pub max_connections: u64, + /// List of node IDs, to which a connection will be (re)established ignoring any existing /// limits #[serde( @@ -475,12 +565,6 @@ pub struct P2PConfig { /// Set `true` to enable the peer-exchange reactor pub pex: bool, - /// Seed mode, in which node constantly crawls the network and looks for - /// peers. If another node asks it for addresses, it responds and disconnects. - /// - /// Does not work if the peer-exchange reactor is disabled. - pub seed_mode: bool, - /// Comma separated list of peer IDs to keep private (will not be gossiped to other peers) #[serde( serialize_with = "serialize_comma_separated_list", @@ -498,22 +582,34 @@ pub struct P2PConfig { pub dial_timeout: Timeout, } +/// Makes it possible to configure which queue backend the P2P layer uses. +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +pub enum P2PQueueType { + #[serde(rename = "fifo")] + FIFO, + #[serde(rename = "priority")] + Priority, +} + +impl Default for P2PQueueType { + fn default() -> Self { + Self::Priority + } +} + /// mempool configuration options #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] pub struct MempoolConfig { + /// Mempool version to use. + pub version: MempoolVersion, + /// Recheck enabled pub recheck: bool, /// Broadcast enabled pub broadcast: bool, - /// WAL dir - #[serde( - deserialize_with = "deserialize_optional_value", - serialize_with = "serialize_optional_value" - )] - pub wal_dir: Option, - /// Maximum number of transactions in the mempool pub size: u64, @@ -528,7 +624,6 @@ pub struct MempoolConfig { /// Do not remove invalid transactions from the cache (default: false) /// Set to true if it's not possible for any invalid transaction to become valid /// again in the future. - #[serde(rename = "keep-invalid-txs-in-cache")] pub keep_invalid_txs_in_cache: bool, /// Maximum size of a single transaction. @@ -539,10 +634,46 @@ pub struct MempoolConfig { /// Including space needed by encoding (one varint per transaction). /// XXX: Unused due to pub max_batch_bytes: u64, + + /// If non-zero, defines the maximum amount of time a transaction can exist + /// for in the mempool. + /// + /// Note, if `ttl_num_blocks` is also defined, a transaction will be removed + /// if it has existed in the mempool at least `ttl_num_blocks` number of + /// blocks or if it's insertion time into the mempool is beyond + /// `ttl_duration`. + pub ttl_duration: Timeout, + + /// If non-zero, defines the maximum number of blocks a transaction can + /// exist for in the mempool. + /// + /// Note, if `ttl_duration` is also defined, a transaction will be removed + /// if it has existed in the mempool at least `ttl_num_blocks` number of + /// blocks or if it's insertion time into the mempool is beyond + /// `ttl_duration`. + pub ttl_num_blocks: u64, +} + +/// The mempool version to use. +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +pub enum MempoolVersion { + /// v0 of the mempool + #[serde(rename = "v0")] + Legacy, + /// v1 of the mempool (the default) + #[serde(rename = "v1")] + Prioritized, +} + +impl Default for MempoolVersion { + fn default() -> Self { + Self::Prioritized + } } /// consensus configuration options #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] pub struct ConsensusConfig { /// Path to WAL file pub wal_file: PathBuf, @@ -593,24 +724,37 @@ pub struct ConsensusConfig { /// transactions indexer configuration options #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] pub struct TxIndexConfig { - /// What indexer to use for transactions + /// The backend database list to back the indexer. If list contains "null" + /// or "", meaning no indexer service will be used. + /// + /// The application will set which txs to index. In some cases a node + /// operator will be able to decide which txs to index based on + /// configuration set in the application. #[serde(default)] - pub indexer: TxIndexer, + pub indexer: Vec, + + /// The PostgreSQL connection configuration, the connection format: + /// `postgresql://:@:/?` + pub psql_conn: String, } /// What indexer to use for transactions #[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub enum TxIndexer { - /// "null" - // TODO(tarcieri): use an `Option` type here? + /// "null" - no indexer #[serde(rename = "null")] Null, - /// "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to - /// levelDB; see DBBackend). + /// "kv" (default) - the simplest possible indexer, backed by key-value + /// storage (defaults to levelDB; see DBBackend). #[serde(rename = "kv")] Kv, + + /// "psql" - the indexer services backed by PostgreSQL. + #[serde(rename = "psql")] + PostgreSQL, } impl Default for TxIndexer { @@ -621,6 +765,7 @@ impl Default for TxIndexer { /// instrumentation configuration options #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] pub struct InstrumentationConfig { /// When `true`, Prometheus metrics are served under /metrics on /// PrometheusListenAddr. @@ -639,6 +784,7 @@ pub struct InstrumentationConfig { /// statesync configuration options #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] pub struct StatesyncConfig { /// 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. @@ -647,23 +793,23 @@ pub struct StatesyncConfig { /// will have a truncated block history, starting from the height of the snapshot. pub enable: bool, - /// RPC servers (comma-separated) for light client verification of the synced state machine and - /// retrieval of state data for node bootstrapping. Also needs a trusted height and - /// corresponding header hash obtained from a trusted source, and a period during which - /// validators can be trusted. - /// - /// For Cosmos SDK-based chains, trust-period should usually be about 2/3 of the unbonding time - /// (~2 weeks) during which they can be financially punished (slashed) for misbehavior. + /// State sync uses light client verification to verify state. This can be + /// done either through the P2P layer or RPC layer. Set this to true to use + /// the P2P layer. If false (default), RPC layer will be used. + pub use_p2p: bool, + + /// If using RPC, at least two addresses need to be provided. They should be + /// compatible with net.Dial, for example: "host.example.com:2125" #[serde( serialize_with = "serialize_comma_separated_list", deserialize_with = "deserialize_comma_separated_list" )] pub rpc_servers: Vec, - /// Trust height. See `rpc_servers` above. + /// The height of a trusted block. Must be within the `trust_period`. pub trust_height: u64, - /// Trust hash. See `rpc_servers` above. + /// The hash of a trusted block. pub trust_hash: String, /// Trust period. See `rpc_servers` above. @@ -675,15 +821,43 @@ pub struct StatesyncConfig { /// 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. pub temp_dir: String, + + /// The timeout duration before re-requesting a chunk, possibly from a + /// different peer (default: 15 seconds). + pub chunk_request_timeout: Timeout, + + /// The number of concurrent chunk and block fetchers to run (default: 4). + #[serde( + serialize_with = "serialize_to_str", + deserialize_with = "deserialize_from_str" + )] + pub fetchers: u16, } -/// fastsync configuration options +/// blocksync configuration options #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] -pub struct FastsyncConfig { - /// Fast Sync version to use: - /// 1) "v0" (default) - the legacy fast sync implementation - /// 2) "v2" - complete redesign of v0, optimized for testability & readability - pub version: String, +#[serde(rename_all = "kebab-case")] +pub struct BlocksyncConfig { + /// If this node is many blocks behind the tip of the chain, BlockSync + /// allows them to catchup quickly by downloading blocks in parallel and + /// verifying their commits + pub enable: bool, + + /// Block Sync version to use: + /// 1) "v0" (default) - the standard Block Sync implementation + /// 2) "v2" - DEPRECATED, please use v0 + pub version: BlocksyncVersion, +} + +/// Block sync version to use. +#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +pub enum BlocksyncVersion { + /// The standard block sync implementation. + #[serde(rename = "v0")] + V0, + /// Deprecated. Please use `V0`. + #[serde(rename = "v1")] + V2, } /// Rate at which bytes can be sent/received @@ -696,67 +870,3 @@ impl TransferRate { self.0 } } - -/// Deserialize `Option` where an empty string indicates `None` -fn deserialize_optional_value<'de, D, T, E>(deserializer: D) -> Result, D::Error> -where - D: de::Deserializer<'de>, - T: FromStr, - E: fmt::Display, -{ - let string = Option::::deserialize(deserializer).map(|str| str.unwrap_or_default())?; - - if string.is_empty() { - return Ok(None); - } - - string - .parse() - .map(Some) - .map_err(|e| D::Error::custom(format!("{}", e))) -} - -fn serialize_optional_value(value: &Option, serializer: S) -> Result -where - S: ser::Serializer, - T: Serialize, -{ - match value { - Some(value) => value.serialize(serializer), - None => "".serialize(serializer), - } -} - -/// Deserialize a comma separated list of types that impl `FromStr` as a `Vec` -fn deserialize_comma_separated_list<'de, D, T, E>(deserializer: D) -> Result, D::Error> -where - D: de::Deserializer<'de>, - T: FromStr, - E: fmt::Display, -{ - let mut result = vec![]; - let string = String::deserialize(deserializer)?; - - if string.is_empty() { - return Ok(result); - } - - for item in string.split(',') { - result.push( - item.parse() - .map_err(|e| D::Error::custom(format!("{}", e)))?, - ); - } - - Ok(result) -} - -/// Serialize a comma separated list types that impl `ToString` -fn serialize_comma_separated_list(list: &[T], serializer: S) -> Result -where - S: ser::Serializer, - T: ToString, -{ - let str_list = list.iter().map(|addr| addr.to_string()).collect::>(); - str_list.join(",").serialize(serializer) -} diff --git a/config/src/error.rs b/config/src/error.rs index 87321578b..4340b235b 100644 --- a/config/src/error.rs +++ b/config/src/error.rs @@ -1,5 +1,6 @@ -use flex_error::{define_error, DisplayOnly}; use std::io::Error as IoError; + +use flex_error::{define_error, DisplayOnly}; use tendermint::Error as TendermintError; define_error! { diff --git a/config/src/lib.rs b/config/src/lib.rs index 4954d0e7e..0c195c3ef 100644 --- a/config/src/lib.rs +++ b/config/src/lib.rs @@ -23,6 +23,7 @@ mod error; mod node_key; mod prelude; mod priv_validator_key; +mod serialization; pub use config::*; pub use error::*; diff --git a/config/src/net.rs b/config/src/net.rs index 49ad3d1c0..5260793a4 100644 --- a/config/src/net.rs +++ b/config/src/net.rs @@ -1,16 +1,16 @@ //! Remote addresses (`tcp://` or `unix://`) -use crate::error::Error; -use crate::prelude::*; - use core::{ fmt::{self, Display}, str::{self, FromStr}, }; + use serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer}; use tendermint::node::{self, info::ListenAddress}; use url::Url; +use crate::{error::Error, prelude::*}; + /// URI prefix for TCP connections pub const TCP_PREFIX: &str = "tcp://"; @@ -128,9 +128,10 @@ impl Serialize for Address { #[cfg(test)] mod tests { - use super::*; use tendermint::node; + use super::*; + const EXAMPLE_TCP_ADDR: &str = "tcp://abd636b766dcefb5322d8ca40011ec2cb35efbc2@35.192.61.41:26656"; const EXAMPLE_TCP_ADDR_WITHOUT_ID: &str = "tcp://35.192.61.41:26656"; @@ -157,7 +158,7 @@ mod tests { ); assert_eq!(host, "35.192.61.41"); assert_eq!(port, 26656); - } + }, other => panic!("unexpected address type: {:?}", other), } } @@ -179,7 +180,7 @@ mod tests { assert!(peer_id.is_none()); assert_eq!(host, "35.192.61.41"); assert_eq!(*port, 26656); - } + }, other => panic!("unexpected address type: {:?}", other), } } @@ -191,7 +192,7 @@ mod tests { match addr { Address::Unix { path } => { assert_eq!(path, "/tmp/node.sock"); - } + }, other => panic!("unexpected address type: {:?}", other), } } @@ -218,7 +219,7 @@ mod tests { // The parser URL strips the leading zeroes and converts to lowercase hex assert_eq!(host, "[2001:0:3238:dfe1:63::fefb]"); assert_eq!(*port, 26656); - } + }, other => panic!("unexpected address type: {:?}", other), } } diff --git a/config/src/node_key.rs b/config/src/node_key.rs index 190265f6d..ba66fb2cc 100644 --- a/config/src/node_key.rs +++ b/config/src/node_key.rs @@ -1,11 +1,11 @@ //! Node keys -use crate::prelude::*; -use serde::{Deserialize, Serialize}; use std::{fs, path::Path}; + +use serde::{Deserialize, Serialize}; use tendermint::{node, private_key::PrivateKey, public_key::PublicKey}; -use crate::error::Error; +use crate::{error::Error, prelude::*}; /// P2P node private keys #[derive(Serialize, Deserialize)] @@ -36,7 +36,7 @@ impl NodeKey { pub fn public_key(&self) -> PublicKey { #[allow(unreachable_patterns)] match &self.priv_key { - PrivateKey::Ed25519(keypair) => keypair.public.into(), + PrivateKey::Ed25519(signing_key) => PublicKey::Ed25519(signing_key.verification_key()), _ => unreachable!(), } } diff --git a/config/src/prelude.rs b/config/src/prelude.rs index 9ff42a989..aa9a20b65 100644 --- a/config/src/prelude.rs +++ b/config/src/prelude.rs @@ -1,11 +1,11 @@ -pub use core::prelude::v1::*; - // Re-export according to alloc::prelude::v1 because it is not yet stabilized // https://doc.rust-lang.org/src/alloc/prelude/v1.rs.html -pub use alloc::borrow::ToOwned; -pub use alloc::boxed::Box; -pub use alloc::string::{String, ToString}; -pub use alloc::vec::Vec; - -pub use alloc::format; -pub use alloc::vec; +pub use alloc::{ + borrow::ToOwned, + boxed::Box, + format, + string::{String, ToString}, + vec, + vec::Vec, +}; +pub use core::prelude::v1::*; diff --git a/config/src/priv_validator_key.rs b/config/src/priv_validator_key.rs index 92608c5d0..fd5274943 100644 --- a/config/src/priv_validator_key.rs +++ b/config/src/priv_validator_key.rs @@ -1,12 +1,15 @@ //! Validator private keys -use crate::prelude::*; -use serde::{Deserialize, Serialize}; use std::{fs, path::Path}; -use tendermint::public_key::TendermintKey; -use tendermint::{account, private_key::PrivateKey, public_key::PublicKey}; -use crate::error::Error; +use serde::{Deserialize, Serialize}; +use tendermint::{ + account, + private_key::PrivateKey, + public_key::{PublicKey, TendermintKey}, +}; + +use crate::{error::Error, prelude::*}; /// Validator private key #[derive(Serialize, Deserialize)] // JSON custom serialization for priv_validator_key.json diff --git a/config/src/serialization.rs b/config/src/serialization.rs new file mode 100644 index 000000000..7cf0af835 --- /dev/null +++ b/config/src/serialization.rs @@ -0,0 +1,91 @@ +//! Serialization utilities + +use core::{fmt, str::FromStr}; + +use serde::{de, de::Error as _, ser, Deserialize, Serialize}; + +use crate::prelude::*; + +/// Deserialize `Option` where an empty string indicates `None` +pub fn deserialize_optional_value<'de, D, T, E>(deserializer: D) -> Result, D::Error> +where + D: de::Deserializer<'de>, + T: FromStr, + E: fmt::Display, +{ + let string = Option::::deserialize(deserializer).map(|str| str.unwrap_or_default())?; + + if string.is_empty() { + return Ok(None); + } + + string + .parse() + .map(Some) + .map_err(|e| D::Error::custom(format!("{}", e))) +} + +pub fn serialize_optional_value(value: &Option, serializer: S) -> Result +where + S: ser::Serializer, + T: Serialize, +{ + match value { + Some(value) => value.serialize(serializer), + None => "".serialize(serializer), + } +} + +/// Deserialize a comma separated list of types that impl `FromStr` as a `Vec` +pub fn deserialize_comma_separated_list<'de, D, T, E>(deserializer: D) -> Result, D::Error> +where + D: de::Deserializer<'de>, + T: FromStr, + E: fmt::Display, +{ + let mut result = vec![]; + let string = String::deserialize(deserializer)?; + + if string.is_empty() { + return Ok(result); + } + + for item in string.split(',') { + result.push( + item.parse() + .map_err(|e| D::Error::custom(format!("{}", e)))?, + ); + } + + Ok(result) +} + +/// Serialize a comma separated list types that impl `ToString` +pub fn serialize_comma_separated_list(list: &[T], serializer: S) -> Result +where + S: ser::Serializer, + T: ToString, +{ + let str_list = list.iter().map(|addr| addr.to_string()).collect::>(); + str_list.join(",").serialize(serializer) +} + +/// Deserialize an item from a string that impl `ToString`. +pub fn deserialize_from_str<'de, D, T, E>(deserializer: D) -> Result +where + D: de::Deserializer<'de>, + T: FromStr, + E: fmt::Display, +{ + let s = String::deserialize(deserializer)?; + s.parse().map_err(|e| D::Error::custom(format!("{}", e))) +} + +/// Serialize a value that impl `ToString` to a string. +pub fn serialize_to_str(value: &T, serializer: S) -> Result +where + S: ser::Serializer, + T: ToString, +{ + value.to_string().serialize(serializer) +} diff --git a/config/tests/mod.rs b/config/tests/mod.rs index 5670e8272..87101c9bc 100644 --- a/config/tests/mod.rs +++ b/config/tests/mod.rs @@ -2,9 +2,10 @@ //! //! Test config files are located in the `tests/support/config` subdirectory. +use std::{fs, path::PathBuf, time::Duration}; + #[cfg(test)] use pretty_assertions::assert_eq; -use std::{fs, path::PathBuf, time::Duration}; use tendermint::node; use tendermint_config::*; @@ -27,7 +28,6 @@ fn config_toml_parser() { "tcp://127.0.0.1:26658".parse::().unwrap() ); assert_eq!(config.moniker.as_ref(), "technodrome"); - assert!(config.fast_sync); assert_eq!(config.db_backend, DbBackend::GoLevelDb); assert_eq!(config.db_dir, PathBuf::from("data")); assert_eq!(config.log_level.global, Some("info".to_string())); @@ -37,14 +37,14 @@ fn config_toml_parser() { assert_eq!(config.log_format, LogFormat::Plain); assert_eq!(config.genesis_file, PathBuf::from("config/genesis.json")); assert_eq!( - config.priv_validator_key_file, - Some(PathBuf::from("config/priv_validator_key.json")) + config.priv_validator.key_file, + PathBuf::from("config/priv_validator_key.json") ); assert_eq!( - config.priv_validator_state_file, + config.priv_validator.state_file, PathBuf::from("data/priv_validator_state.json") ); - assert_eq!(config.priv_validator_laddr, None); + assert_eq!(config.priv_validator.laddr, None); assert_eq!(config.node_key_file, PathBuf::from("config/node_key.json")); assert_eq!(config.abci, AbciMode::Socket); assert!(!config.filter_peers); @@ -117,11 +117,10 @@ fn config_toml_parser() { assert_eq!(p2p.max_num_inbound_peers, 40); assert_eq!(p2p.max_num_outbound_peers, 10); assert_eq!(*p2p.flush_throttle_timeout, Duration::from_millis(100)); - assert_eq!(p2p.max_packet_msg_payload_size, 1024); + assert_eq!(p2p.max_packet_msg_payload_size, 1400); assert_eq!(p2p.send_rate.bytes_per_sec(), 5_120_000); assert_eq!(p2p.recv_rate.bytes_per_sec(), 5_120_000); assert!(p2p.pex); - assert!(!p2p.seed_mode); assert_eq!(p2p.private_peer_ids.len(), 3); assert_eq!( p2p.private_peer_ids[0], @@ -150,7 +149,6 @@ fn config_toml_parser() { let mempool = &config.mempool; assert!(mempool.recheck); assert!(mempool.broadcast); - assert_eq!(mempool.wal_dir, None); assert_eq!(mempool.size, 5000); assert_eq!(mempool.max_txs_bytes, 1_073_741_824); assert_eq!(mempool.cache_size, 10000); @@ -168,7 +166,7 @@ fn config_toml_parser() { *consensus.timeout_precommit_delta, Duration::from_millis(500) ); - assert_eq!(*consensus.timeout_commit, Duration::from_secs(5)); + assert_eq!(*consensus.timeout_commit, Duration::from_secs(1)); assert!(!consensus.skip_timeout_commit); assert_eq!( *consensus.create_empty_blocks_interval, @@ -186,7 +184,7 @@ fn config_toml_parser() { // transactions indexer configuration options let tx_index = &config.tx_index; - assert_eq!(tx_index.indexer, TxIndexer::Kv); + assert_eq!(tx_index.indexer, vec![TxIndexer::Kv]); // instrumentation configuration options diff --git a/config/tests/support/config/config.toml b/config/tests/support/config/config.toml index d13022e5a..05f739ddc 100644 --- a/config/tests/support/config/config.toml +++ b/config/tests/support/config/config.toml @@ -12,15 +12,22 @@ # TCP or UNIX socket address of the ABCI application, # or the name of an ABCI application compiled in with the Tendermint binary -proxy_app = "tcp://127.0.0.1:26658" +proxy-app = "tcp://127.0.0.1:26658" # A custom human readable name for this node moniker = "technodrome" -# If this node is many blocks behind the tip of the chain, FastSync -# allows them to catchup quickly by downloading blocks in parallel -# and verifying their commits -fast_sync = true +# Mode of Node: full | validator | seed +# * validator node +# - all reactors +# - with priv_validator_key.json, priv_validator_state.json +# * full node +# - all reactors +# - No priv_validator_key.json, priv_validator_state.json +# * seed node +# - only P2P, PEX Reactor +# - No priv_validator_key.json, priv_validator_state.json +mode = "validator" # Database backend: goleveldb | cleveldb | boltdb | rocksdb | badgerdb # * goleveldb (github.com/syndtr/goleveldb - most popular implementation) @@ -41,41 +48,58 @@ fast_sync = true # * badgerdb (uses github.com/dgraph-io/badger) # - EXPERIMENTAL # - use badgerdb build tag (go build -tags badgerdb) -db_backend = "goleveldb" +db-backend = "goleveldb" # Database directory -db_dir = "data" +db-dir = "data" # Output level for logging, including package level options -log_level = "info" +log-level = "info" # Output format: 'plain' (colored text) or 'json' -log_format = "plain" +log-format = "plain" ##### additional base config options ##### # Path to the JSON file containing the initial validator set and other meta data -genesis_file = "config/genesis.json" +genesis-file = "config/genesis.json" + +# Path to the JSON file containing the private key to use for node authentication in the p2p protocol +node-key-file = "config/node_key.json" + +# Mechanism to connect to the ABCI application: socket | grpc +abci = "socket" + +# If true, query the ABCI app on connecting to a new peer +# so the app can decide if we should keep the connection or not +filter-peers = false + + +####################################################### +### Priv Validator Configuration ### +####################################################### +[priv-validator] # Path to the JSON file containing the private key to use as a validator in the consensus protocol -priv_validator_key_file = "config/priv_validator_key.json" +key-file = "config/priv_validator_key.json" # Path to the JSON file containing the last sign state of a validator -priv_validator_state_file = "data/priv_validator_state.json" +state-file = "data/priv_validator_state.json" # TCP or UNIX socket address for Tendermint to listen on for # connections from an external PrivValidator process -priv_validator_laddr = "" +# when the listenAddr is prefixed with grpc instead of tcp it will use the gRPC Client +laddr = "" -# Path to the JSON file containing the private key to use for node authentication in the p2p protocol -node_key_file = "config/node_key.json" +# Path to the client certificate generated while creating needed files for secure connection. +# If a remote validator address is provided but no certificate, the connection will be insecure +client-certificate-file = "" -# Mechanism to connect to the ABCI application: socket | grpc -abci = "socket" +# Client key generated while creating certificates for secure connection +client-key-file = "" -# If true, query the ABCI app on connecting to a new peer -# so the app can decide if we should keep the connection or not -filter_peers = false +# Path to the Root Certificate Authority used to sign both client and server certificates +root-ca-file = "" ####################################################################### @@ -93,171 +117,240 @@ laddr = "tcp://0.0.0.0:26657" # A list of origins a cross-domain request can be executed from # Default value '[]' disables cors support # Use '["*"]' to allow any origin -cors_allowed_origins = [] +cors-allowed-origins = [] # A list of methods the client is allowed to use with cross-domain requests -cors_allowed_methods = ["HEAD", "GET", "POST", ] +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", ] +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 = "" +# Deprecated gRPC in the RPC layer of Tendermint will be deprecated in 0.36. +grpc-laddr = "" # Maximum number of simultaneous connections. -# Does not include RPC (HTTP&WebSocket) connections. See max_open_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 +# Deprecated gRPC in the RPC layer of Tendermint will be deprecated in 0.36. +grpc-max-open-connections = 900 -# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool +# 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 +# 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. # Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files} # 1024 - 40 - 10 - 50 = 924 = ~900 -max_open_connections = 900 +max-open-connections = 900 # 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 +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. -max_subscriptions_per_client = 5 +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. # See https://github.com/tendermint/tendermint/issues/3435 -timeout_broadcast_tx_commit = "10s" +timeout-broadcast-tx-commit = "10s" # Maximum size of request body, in bytes -max_body_bytes = 1000000 +max-body-bytes = 1000000 # Maximum size of request header, in bytes -max_header_bytes = 1048576 +max-header-bytes = 1048576 # The path to a file containing certificate that is used to create the HTTPS server. # Might be either absolute path or path related to Tendermint's config directory. # If the certificate is signed by a certificate authority, # the certFile should be the concatenation of the server's certificate, any intermediates, # and the CA's certificate. -# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server. +# NOTE: both tls-cert-file and tls-key-file must be present for Tendermint to create HTTPS server. # Otherwise, HTTP server is run. -tls_cert_file = "" +tls-cert-file = "" # 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 Tendermint's config directory. # NOTE: both tls-cert-file and tls-key-file must be present for Tendermint to create HTTPS server. # Otherwise, HTTP server is run. -tls_key_file = "" +tls-key-file = "" # pprof listen address (https://golang.org/pkg/net/http/pprof) -pprof_laddr = "" +pprof-laddr = "" ####################################################### ### P2P Configuration Options ### ####################################################### [p2p] +# Enable the legacy p2p layer. +use-legacy = false + +# Select the p2p internal queue +queue-type = "priority" + # 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. -external_address = "" +# 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 +# We only use these if we can’t connect to peers in the addrbook +# NOTE: not used by the new PEX reactor. Please use BootstrapPeers instead. +# TODO: Remove once p2p refactor is complete +# ref: https:#github.com/tendermint/tendermint/issues/5670 seeds = "c2e1bde78877975b31e6f06e77da200a38048e2b@seed-1.example.com:26656,0eafed3e9e76f626a299e1b8a79454fffe9ca83c@seed-2.example.com:26656" +# 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 = "" + # Comma separated list of nodes to keep persistent connections to -persistent_peers = "tcp://70d834561f91613153e4a873f01a2cbbf1b9678d@1.2.3.4:26656,tcp://f68ed33a0baa0c734a939a9e60659566adc725cd@peer-2.example.com:26656" +persistent-peers = "tcp://70d834561f91613153e4a873f01a2cbbf1b9678d@1.2.3.4:26656,tcp://f68ed33a0baa0c734a939a9e60659566adc725cd@peer-2.example.com:26656" # UPNP port forwarding upnp = false # Path to address book -addr_book_file = "config/addrbook.json" +# TODO: Remove once p2p refactor is complete in favor of peer store. +addr-book-file = "config/addrbook.json" # Set true for strict address routability rules # Set false for private or local networks -addr_book_strict = true +addr-book-strict = true # Maximum number of inbound peers -max_num_inbound_peers = 40 +# +# TODO: Remove once p2p refactor is complete in favor of MaxConnections. +# ref: https://github.com/tendermint/tendermint/issues/5670 +max-num-inbound-peers = 40 # Maximum number of outbound peers to connect to, excluding persistent peers -max_num_outbound_peers = 10 +# +# TODO: Remove once p2p refactor is complete in favor of MaxConnections. +# ref: https://github.com/tendermint/tendermint/issues/5670 +max-num-outbound-peers = 10 + +# Maximum number of connections (inbound and outbound). +max-connections = 64 + +# Rate limits the number of incoming connection attempts per IP address. +max-incoming-connection-attempts = 100 # List of node IDs, to which a connection will be (re)established ignoring any existing limits -unconditional_peer_ids = "" +# TODO: Remove once p2p refactor is complete. +# ref: https://github.com/tendermint/tendermint/issues/5670 +unconditional-peer-ids = "" # Maximum pause when redialing a persistent peer (if zero, exponential backoff is used) -persistent_peers_max_dial_period = "0s" +# TODO: Remove once p2p refactor is complete +# ref: https:#github.com/tendermint/tendermint/issues/5670 +persistent-peers-max-dial-period = "0s" # Time to wait before flushing messages out on the connection -flush_throttle_timeout = "100ms" +# TODO: Remove once p2p refactor is complete +# ref: https:#github.com/tendermint/tendermint/issues/5670 +flush-throttle-timeout = "100ms" # Maximum size of a message packet payload, in bytes -max_packet_msg_payload_size = 1024 +# TODO: Remove once p2p refactor is complete +# ref: https:#github.com/tendermint/tendermint/issues/5670 +max-packet-msg-payload-size = 1400 # Rate at which packets can be sent, in bytes/second -send_rate = 5120000 +# TODO: Remove once p2p refactor is complete +# ref: https:#github.com/tendermint/tendermint/issues/5670 +send-rate = 5120000 # Rate at which packets can be received, in bytes/second -recv_rate = 5120000 +# TODO: Remove once p2p refactor is complete +# ref: https:#github.com/tendermint/tendermint/issues/5670 +recv-rate = 5120000 # Set true to enable the peer-exchange reactor pex = true -# Seed mode, in which node constantly crawls the network and looks for -# peers. If another node asks it for addresses, it responds and disconnects. -# -# Does not work if the peer-exchange reactor is disabled. -seed_mode = false - # Comma separated list of peer IDs to keep private (will not be gossiped to other peers) -private_peer_ids = "8112e5c5ab6a48adcc0e875d58a4264a2639f6a8,3d1b9086e48c7bdf7f0d766351eed812a75de500,a7306aee50627e68177a002badd3ba4a45301ad4" +# Warning: IPs will be exposed at /net_info, for more information https://github.com/tendermint/tendermint/issues/3055 +private-peer-ids = "8112e5c5ab6a48adcc0e875d58a4264a2639f6a8,3d1b9086e48c7bdf7f0d766351eed812a75de500,a7306aee50627e68177a002badd3ba4a45301ad4" # Toggle to disable guard against peers connecting from the same ip. -allow_duplicate_ip = false +allow-duplicate-ip = false # Peer connection configuration. -handshake_timeout = "20s" -dial_timeout = "3s" +handshake-timeout = "20s" +dial-timeout = "3s" ####################################################### ### Mempool Configuration Option ### ####################################################### [mempool] +# Mempool version to use: +# 1) "v0" - The legacy non-prioritized mempool reactor. +# 2) "v1" (default) - The prioritized mempool reactor. +version = "v1" + recheck = true broadcast = true -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 +# max-txs-bytes=5MB, mempool will only accept 5 transactions). +max-txs-bytes = 1073741824 # Size of the cache (used to filter transactions we saw earlier) in transactions -cache_size = 10000 +cache-size = 10000 # Do not remove invalid transactions from the cache (default: false) # Set to true if it's not possible for any invalid transaction to become valid @@ -265,13 +358,29 @@ cache_size = 10000 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 +# 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 = 0 +max-batch-bytes = 0 + +# ttl-duration, if non-zero, defines the maximum amount of time a transaction +# can exist for in the mempool. +# +# Note, if ttl-num-blocks is also defined, a transaction will be removed if it +# has existed in the mempool at least ttl-num-blocks number of blocks or if it's +# insertion time into the mempool is beyond ttl-duration. +ttl-duration = "0s" + +# ttl-num-blocks, if non-zero, defines the maximum number of blocks a transaction +# can exist for in the mempool. +# +# Note, if ttl-duration is also defined, a transaction will be removed if it +# has existed in the mempool at least ttl-num-blocks number of blocks or if +# it's insertion time into the mempool is beyond ttl-duration. +ttl-num-blocks = 0 ####################################################### ### State Sync Configuration Options ### @@ -284,33 +393,52 @@ max_batch_bytes = 0 # starting from the height of the snapshot. enable = false -# RPC servers (comma-separated) for light client verification of the synced state machine and -# retrieval of state data for node bootstrapping. Also needs a trusted height and corresponding -# header hash obtained from a trusted source, and a period during which validators can be trusted. -# -# For Cosmos SDK-based chains, trust_period should usually be about 2/3 of the unbonding time (~2 -# weeks) during which they can be financially punished (slashed) for misbehavior. -rpc_servers = "" -trust_height = 0 -trust_hash = "" -trust_period = "168h0m0s" +# State sync uses light client verification to verify state. This can be done either through the +# P2P layer or RPC layer. Set this to true to use the P2P layer. If false (default), RPC layer +# will be used. +use-p2p = false + +# If using RPC, at least two addresses need to be provided. They should be compatible with net.Dial, +# for example: "host.example.com:2125" +rpc-servers = "" + +# The hash and height of a trusted block. Must be within the trust-period. +trust-height = 0 +trust-hash = "" + +# The trust period should be set so that Tendermint can detect and gossip misbehavior before +# it is considered expired. For chains based on the Cosmos SDK, one day less than the unbonding +# period should suffice. +trust-period = "168h0m0s" # Time to spend discovering snapshots before initiating a restore. -discovery_time = "15s" +discovery-time = "15s" + +# Temporary directory for state sync snapshot chunks, defaults to os.TempDir(). +# The synchronizer will create a new, randomly named directory within this directory +# and remove it when the sync is complete. +temp-dir = "" -# 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: 15 seconds). +chunk-request-timeout = "15s" + +# The number of concurrent chunk and block fetchers to run (default: 4). +fetchers = "4" ####################################################### -### Fast Sync Configuration Connections ### +### Block Sync Configuration Connections ### ####################################################### -[fastsync] +[blocksync] -# Fast Sync version to use: -# 1) "v0" (default) - the legacy fast sync implementation -# 2) "v1" - refactor of v0 version for better testability -# 2) "v2" - complete redesign of v0, optimized for testability & readability +# If this node is many blocks behind the tip of the chain, BlockSync +# allows them to catchup quickly by downloading blocks in parallel +# and verifying their commits +enable = true + +# Block Sync version to use: +# 1) "v0" (default) - the standard Block Sync implementation +# 2) "v2" - DEPRECATED, please use v0 version = "v0" ####################################################### @@ -318,48 +446,49 @@ version = "v0" ####################################################### [consensus] -wal_file = "data/cs.wal/wal" +wal-file = "data/cs.wal/wal" # How long we wait for a proposal block before prevoting nil -timeout_propose = "3s" -# How much timeout_propose increases with each round -timeout_propose_delta = "500ms" +timeout-propose = "3s" +# How much timeout-propose increases with each round +timeout-propose-delta = "500ms" # How long we wait after receiving +2/3 prevotes for “anything” (ie. not a single block or nil) -timeout_prevote = "1s" -# How much the timeout_prevote increases with each round -timeout_prevote_delta = "500ms" +timeout-prevote = "1s" +# How much the timeout-prevote increases with each round +timeout-prevote-delta = "500ms" # How long we wait after receiving +2/3 precommits for “anything” (ie. not a single block or nil) -timeout_precommit = "1s" -# How much the timeout_precommit increases with each round -timeout_precommit_delta = "500ms" +timeout-precommit = "1s" +# How much the timeout-precommit increases with each round +timeout-precommit-delta = "500ms" # How long we 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). -timeout_commit = "5s" +timeout-commit = "1s" # How many blocks to look back to check existence of the node's consensus votes before joining consensus # When non-zero, the node will panic upon restart -# if the same consensus key was used to sign {double_sign_check_height} last blocks. +# if the same consensus key was used to sign {double-sign-check-height} last blocks. # So, validators should stop the state machine, wait for some blocks, and then restart the state machine to avoid panic. -double_sign_check_height = 0 +double-sign-check-height = 0 # Make progress as soon as we have all the precommits (as if TimeoutCommit = 0) -skip_timeout_commit = false +skip-timeout-commit = false # EmptyBlocks mode and possible interval between empty blocks -create_empty_blocks = true -create_empty_blocks_interval = "0s" +create-empty-blocks = true +create-empty-blocks-interval = "0s" # Reactor sleep duration parameters -peer_gossip_sleep_duration = "100ms" -peer_query_maj23_sleep_duration = "2s" +peer-gossip-sleep-duration = "100ms" +peer-query-maj23-sleep-duration = "2s" ####################################################### ### Transaction Indexer Configuration Options ### ####################################################### -[tx_index] +[tx-index] -# What indexer to use for transactions +# The backend database list to back the indexer. +# If list contains "null" or "", meaning no indexer service will be used. # # The application will set which txs to index. In some cases a node operator will be able # to decide which txs to index based on configuration set in the application. @@ -367,8 +496,13 @@ peer_query_maj23_sleep_duration = "2s" # Options: # 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. -indexer = "kv" +# 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 ### @@ -381,13 +515,13 @@ indexer = "kv" prometheus = false # Address to listen for Prometheus collector(s) connections -prometheus_listen_addr = ":26660" +prometheus-listen-addr = ":26660" # Maximum number of simultaneous connections. # If you want to accept a larger number than the default, make sure # you increase your OS limits. # 0 - unlimited. -max_open_connections = 3 +max-open-connections = 3 # Instrumentation namespace namespace = "tendermint" diff --git a/docs/architecture/README.md b/docs/architecture/README.md index 9d4e4dd0f..e7a894577 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -1,30 +1,30 @@ # Architecture Decision Records (ADR) -This is a location to record all high-level architecture decisions in the Tendermint-RS project. +This is a location to record all high-level architecture decisions in the +tendermint-rs project. -You can read more about the ADR concept in this [blog post](https://product.reverb.com/documenting-architecture-decisions-the-reverb-way-a3563bb24bd0#.78xhdix6t). +You can read more about the ADR concept in this [blog +post](https://product.reverb.com/documenting-architecture-decisions-the-reverb-way-a3563bb24bd0#.78xhdix6t). An ADR should provide: -- Context on the relevant goals and the current state -- Proposed changes to achieve the goals -- Summary of pros and cons +- Context on the relevant goals and the current state to explain why a decision + must be made now +- The decision that will allow us to achieve the goals +- Summary of pros and cons if we make the decision - References - Changelog -Note the distinction between an ADR and a spec. The ADR provides the context, intuition, reasoning, and -justification for a change in architecture, or for the architecture of something -new. The spec is much more compressed and streamlined summary of everything as -it is or should be. +Note the distinction between an ADR and a spec. The ADR provides the context, +intuition, reasoning, and justification for a change in architecture, or for the +architecture of something new. The spec is a much more compressed and +streamlined summary of everything as it is or should be. -If recorded decisions turned out to be lacking, convene a discussion, record the new decisions here, and then modify the code to match. +If recorded decisions turned out to be lacking, convene a discussion, record the +new decisions here, and then modify the code to match. Note the context/background should be written in the present tense. -To suggest an ADR, please make use of the [ADR template](./adr-template.md) provided. +To suggest an ADR, please make use of the [ADR template](./adr-template.md) +provided. -## Table of Contents - -| ADR \# | Description | Status | -| ------ | ----------- | ------ | -| [001](./adr-001-repo.md) | Repository structure for `tendermint-rs` | Proposed | diff --git a/docs/architecture/adr-009-transport-agnostic-peer-abstraction.md b/docs/architecture/adr-009-transport-agnostic-peer-abstraction.md index 792b22061..95237fbe8 100644 --- a/docs/architecture/adr-009-transport-agnostic-peer-abstraction.md +++ b/docs/architecture/adr-009-transport-agnostic-peer-abstraction.md @@ -2,6 +2,7 @@ ## Changelog * 2021-02-05: drafted +* 2022-04-08: revised ## Context @@ -32,9 +33,9 @@ resources on the system. pub trait Transport { type Connection: Connection; type Endpoint: Endpoint::Connection>; - type Incoming: Iterator::Connection>> + Send; + type Incoming: Stream::Connection>> + Send + Sync; - fn bind(self, bind_info: BindInfo) -> Result<(Self::Endpoint, Self::Incoming)>; + async fn bind(self, bind_info: BindInfo) -> Result<(Self::Endpoint, Self::Incoming)>; } ``` @@ -43,10 +44,10 @@ incoming `Connection`s. Which is a standardised way to connect to new peers and react to newly connected ones respectively. ``` rust -pub trait Endpoint: Send { +pub trait Endpoint: Send + Sync { type Connection; - fn connect(&self, info: ConnectInfo) -> Result; + async fn connect(&self, info: ConnectInfo) -> Result; fn listen_addrs(&self) -> Vec; } ``` @@ -58,19 +59,19 @@ While being open to enable feature parity with current production installations based on tendermint-go's `MConn`. ``` rust -pub trait StreamSend { - fn send>(msg: B) -> Result<()>; +pub trait StreamSend: Send + Sync { + async fn send>(msg: B) -> Result<()>; } -pub trait Connection: Send { +pub trait Connection: Send + Sync { type Error: std::error::Error + Send + Sync + 'static; - type StreamRead: Iterator>> + Send; + type StreamRead: Stream>> + Send; type StreamSend: StreamSend; fn advertised_addrs(&self) -> Vec; - fn close(&self) -> Result<()>; + async fn close(&self) -> Result<()>; fn local_addr(&self) -> SocketAddr; - fn open_bidirectional( + async fn open_bidirectional( &self, stream_id: StreamId, ) -> Result<(Self::StreamRead, Self::StreamSend), Self::Error>; @@ -96,11 +97,11 @@ impl Peer> where Conn: Connection, { - pub fn run(self, stream_ids: Vec) -> Result>> { + pub async fn run(self, stream_ids: Vec) -> Result>> { // ... } - fn stop(self) -> Result> { + async fn stop(self) -> Result> { // ... } } @@ -109,11 +110,11 @@ impl Peer> where Conn: Connection, { - pub fn send(&self, message: message::Send) -> Result<()> { + pub async fn send(&self, message: message::Send) -> Result<()> { // ... } - pub fn stop(self) -> Result> { + pub async fn stop(self) -> Result> { // ... } } @@ -123,7 +124,6 @@ While sending messages is done through a method on a running peer, getting hold of incoming messages can be achieved by draining the `Receiver` part of the running state. - ### Supervisor The `Supervisor` is the main entry point to the p2p package giving higher-level @@ -146,19 +146,31 @@ pub enum Event { UpgradeFailed(node::Id, Report), } +struct CommandHandle; + +impl CommandHandle { + fn instruct(command: Command) -> Result<()> { + // .. + } +} + impl Supervisor { - pub fn run(transport: T) -> Result + pub fn new(transport: T) -> Self where T: transport::Transport + Send + 'static, { - // ... + // .. } - pub fn recv(&self) -> Result { - // ... + pub handle(&self) -> CommandHandle { + // .. + } + + pub subscribe(&self) -> Receiver { + // .. } - pub fn command(&self, cmd: Command) -> Result<()> { + pub async fn run(self) -> Result<()> { // ... } } @@ -166,7 +178,7 @@ impl Supervisor { ## Status -Proposed +Accepted ## Consequences diff --git a/docs/architecture/adr-010-time-api-sanity.md b/docs/architecture/adr-010-time-api-sanity.md new file mode 100644 index 000000000..4b1ae7069 --- /dev/null +++ b/docs/architecture/adr-010-time-api-sanity.md @@ -0,0 +1,150 @@ +# ADR 010: Improvements of Time API, internal representation, and serialization + +## Changelog + +* 2021-11-29: Created the ADR. + +## Context + +The `Time` type is defined in `tendermint` to provide a data type for time +calculations with better safety and ergonomics than the `prost`-dictated +`Timestamp` struct, defined in `tendermint-proto` based on Google's +common protobuf message description. +[Concerns](https://github.com/informalsystems/tendermint-rs/issues/865) have +been raised about the need for such a type in the API; however, as we +currently lack a well-supported library in the Rust ecosystem that would provide +the desirable formatting through serde and enforce a range of usable values, +the domain type seems to be necessary. + +The current API of `Time` has the following problems: + +* It's a newtype struct publicly exposing a `DateTime` inner value + provided by the `chrono` crate. `chrono` has a known + [issue][RUSTSEC-2020-0159] with soundness and security and there is no ETA yet + on getting it fixed. + The dependency on chrono triggers cargo audit failures for every project + using the `tendermint` library. + +* The range of usable values supported by `Time` has not been explicitly + defined or enforced. Currently `Time` allows values which can't have + a valid RFC 3339 representation and whose equivalent Unix timestamp values + are not allowed by the Google protobuf specification of `Timestamp`. + +* The serde implementations for `Time` and the proto `Timestamp` struct + always serialize or expect the value as a string, even in serialization + formats that are not human-readable and allow a more efficient binary + representation. + +* Arithmetic operators have been provided for `Time` via `Add`/`Sub` trait + implementations. However, the `Result` output type is + [suprising][guideline-overload] and makes for poor usability of overloaded + operators. + +* Arithmetic and comparison operations are much slower on parsed date/time + structures than on an integer timestamp representation. + If `Time` is meant to be used in performance-sensitive workloads + for operations with date-time values, such as offsetting by a duration, + time difference, or time comparisons, its internal representation should be + more optimized for integer arithmetics. + +* The `Time::as_rfc3339` conversion method is + [named improperly][guideline-naming] with regard to Rust naming guidelines. + +[RUSTSEC-2020-0159]: https://rustsec.org/advisories/RUSTSEC-2020-0159.html +[guideline-overload]: https://rust-lang.github.io/api-guidelines/predictability.html#c-overload +[guideline-naming]: https://rust-lang.github.io/api-guidelines/naming.html#c-conv + +## Decision + +Make these changes, possibly in steps: + +* Make the inner member(s) of the `Time` struct private. + +* Specify that only date-times in the year range 1-9999 inclusive + can be represented by a `Time` value. This matches the restrictions + specified in the Google protobuf message definition for `Timestamp`. + +* Remove conversions from/to `chrono::DateTime`, + introducing these impls instead: + * `impl TryFrom for Time` + (fallible due to the additional range restrictions) + * `impl From