* Initial commit * Add three timeouts and align pseudocode better with existing algorithm * Align protocol with Tendermint code and add find valid value mechanism * Prepare to Nuke Develop (#47) * state -> step * vote -> v * New version of the algorithm and the proof * New version of the algorithm and the proofs * Added algorithm description * Add algorithm description * Add introduction * Add conclusion * Add conclusion file * fix warnings (caption was defined twice) - only the latter is used anyways (centers captions) - this makes it possible to autom. building the paper * Update grammar * s/state_p/step_p * Address Ismail's comments * intro: language fixes * definitions: language fixes * consensus: various fixes * proof: some fixes * try to improve reviewability * \eq -> = * textwrap to 79 * various minor fixes * proof: fix itemization * proof: more minor fixes * proof: timeouts are functions * proof: fixes to lemma6 * Intro changes and improve title page * Add Marko and Ming to acks * add readme * Format algorithm correctly Clarify condition semantic and timeouts Improve descriptions * patform -> platform * Ensure that rules are mutually exclusive - various clarifications and small improvements * Release v0.6 * small nits for smoother readability * This PR is to create signed commits to be able to merge (#50) Signed-off-by: Marko Baricevic <marbar3778@yahoo.com> * Add consesnus and blockchain specs, (#52) - Open questions - Do we want to split lite client work from consesnsus - From the blockchain spec, is encoding nessecary in the spec Signed-off-by: Marko Baricevic <marbar3778@yahoo.com> * Add ABCI SPEC (#51) - move the abci spec from tendermint to spec repo Signed-off-by: Marko Baricevic <marbar3778@yahoo.com> * spec/consensus/signing: add more details about nil and amnesia (#54) - Add more details about nil votes and about amnesia attacks Signed-off-by: Marko Baricevic <marbar3778@yahoo.com> * Add Section for P2P (#53) * Add Section for P2P - moved over the section on p2p Signed-off-by: Marko Baricevic <marbar3778@yahoo.com> * add some more files Signed-off-by: Marko Baricevic <marbar3778@yahoo.com> * Fix model section * Add non-recursive specification of Bisection algorithm - Fix timing issues by introducing Delta parameter * spec: update spec with tendermint updates (#62) * spec: update spec with tendermint updates - this in preperation of deleting the spec folder in docs in tendermint/tendermint Signed-off-by: Marko Baricevic <marbar3778@yahoo.com> * spec: added in reactors & p2p Signed-off-by: Marko Baricevic <marbar3778@yahoo.com> * spec: update readme in spec to comply with docs site Signed-off-by: Marko Baricevic <marbar3778@yahoo.com> * docs: addded more changes from tednermint/tendermint Signed-off-by: Marko Baricevic <marbar3778@yahoo.com> * reflect breaking changes made to Commit (#63) * reflect breaking changes made to Commit PR: https://github.com/tendermint/tendermint/pull/4146 Issue: https://github.com/tendermint/tendermint/issues/1648 * types: rename Commit#Precommits to Signatures * update BlockIDFlagAbsent comment * remove iota * Clean up error conditions and simplify pseudocode * Apply suggestions from code review Co-Authored-By: Anca Zamfir <ancazamfir@users.noreply.github.com> * Add spec doc about unconditional_peer, persistent_peers_max_dial of ADR-050 (#68) * Add spec doc about unconditional_peer_ids, persistent_peers_max_dial_period of ADR-050 * Add indefinitely dialing condition * Add sr25519 amino documentation (#67) * sr25519 amino * Update spec/blockchain/encoding.md Co-Authored-By: Marko <marbar3778@yahoo.com> * some suggestions for pseuodocode changes * Improved error handling * Add explanation on difference between trusted models * Address reviewer's comments * Addressing reviewer's comments * Separating algorithm from proofs * Intermediate commit (aligning spec with the code) * Removing Store from API and providing end-to-end timing guarantees * Address reviewer comment's. Intermediate commit * light client dir and readmes * titles * add redirects * add diagram * detection TODO * fix image * update readme * Aligh the correctness arguments with the pseudocode changes * lite->light * Fix link in readme ./light -> ./light-client * p2p: Merlin based malleability fixes (#72) * Update the secret connection spec with the use of merlin to eliminte handshake malleability * Update spec/p2p/peer.md Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * Update spec/p2p/peer.md Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * Update spec/p2p/peer.md Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com> * docs: update specs to remove cmn (#77) - cmn was remvoed in favor of sub pkgs. cmn.kvpair is now kv.pair Signed-off-by: Marko Baricevic <marbar3778@yahoo.com> * evidence: Add time to evidence params (#69) * evidence: Add time to evidence params - this pr is grouped together with https://github.com/tendermint/tendermint/pull/4254, once that PR is merged then this one can be as well. Signed-off-by: Marko Baricevic <marbar3778@yahoo.com> * remove note Signed-off-by: Marko Baricevic <marbar3778@yahoo.com> * Apply suggestions from code review Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com> * update link to the pex reactor * add markdown link checker * changed tab spacing * removed folder-path flag * first attempt at fixing all links * second attempt at fixing all links * codeowners: add code owners (#82) * codeowners: add code owners - added some codeowners please comment if youd like to be added as well. Signed-off-by: Marko Baricevic <marbar3778@yahoo.com> * remove comment of repo maintainers * remove .idea dir (#83) Signed-off-by: Marko Baricevic <marbar3778@yahoo.com> * RFC-001: configurable block retention (#84) * Added RFC for truncated block history coordination * Clarified minimum block retention * Added hard checks on block retention and snapshot interval, and made some minor tweaks * Genesis parameters are immutable * Use local config for snapshot interval * Reordered parameter descriptions * Clarified local config option for snapshot-interval * rewrite for ABCI commit response * Renamed RFC * add block retention diagram * Removed retain_blocks table * fix image numbers * resolved open questions * image quality * accept RFC-001 (#86) * abci: add basic description of ABCI Commit.ResponseHeight (#85) Documentation for block pruning, once it's merged: tendermint/tendermint#4588. Minimum documentation, for now - we probably shouldn't encourage using this feature too much until we release state sync. * abci: add MaxAgeNumBlocks/MaxAgeDuration to EvidenceParams (#87) * abci: update MaxAgeNumBlocks & MaxAgeDuration docs (#88) * document state sync ABCI interface and P2P protocol (#90) The corresponding Tendermint PRs are tendermint/tendermint#4704 and tendermint/tendermint#4705. * Revert "document state sync ABCI interface and P2P protocol (#90)" (#92) This reverts commit9842b4b0fb. * blockchain: change validator set sorting method (#91) * abci: specify sorting of RequestInitChain.Validators * blockchain: change validator sorting method Refs https://github.com/tendermint/tendermint/issues/2478 * reactors/pex: specify hash function (#94) https://github.com/tendermint/tendermint/pull/4810/files * document state sync ABCI interface and P2P protocol (#93) * Revert "Revert "document state sync ABCI interface and P2P protocol (#90)" (#92)" This reverts commit90797cef90. * update with new enum case * fix links Co-authored-by: Erik Grinaker <erik@interchain.berlin> * Update evidence params with MaxNum (#95) evidence params now includes maxNum which is the maximum number of evidence that can be committed on a single block * reactors/pex: masked IP is used as group key (#96) * spec: add ProofTrialPeriod to EvidenceParam (#99) * spec: modify Header.LastResultsHash (#97) Refs: https://github.com/tendermint/tendermint/issues/1007 PR: https://github.com/tendermint/tendermint/pull/4845 * spec: link to abci server implementations (#100) * spec: update evidence in blockchain.md (#108) now evidence reflects the actual evidence present in the tendermint repo * abci: add AppVersion to ConsensusParams (#106) * abci: tweak node sync estimate (#115) * spec/abci: expand on Validator#Address (#118) Refs https://github.com/tendermint/tendermint/issues/3732 * blockchain: rename to core (#123) * blockchain: remove duplicate evidence sections (#124) * spec/consensus: canonical vs subjective commit Refs https://github.com/tendermint/tendermint/issues/2769 * Apply suggestions from code review Co-authored-by: Igor Konnov <igor.konnov@gmail.com> * update spec with the removal of phantom validator evidence (#126) * bring blockchain back * add correct links * spec: revert event hashing (#132) * Evidence time is sourced from block time (#138) * RFC-002: non-zero genesis (#119) * abci: add ResponseInitChain.app_hash (#140) * update hashing of empty inputs, and initial block LastResultsHash (#141) * update evidence verification (#139) * accept RFC-002 (#142) * add description of arbitrary initial height (#135) * update ResponseInitChain.app_hash description (#143) * remove unused directories and update README (#145) This change removes unused directories (`papers` and `research`) and updates the README to reflect our strategy for merging the informalsystems/tendermint-rs specs into this repository. Partially addresses #121. * ci: add markdown linter (#146) * ci: add dependabot config (#148) * build(deps): bump gaurav-nelson/github-action-markdown-link-check from 0.6.0 to 1.0.7 (#149) Bumps [gaurav-nelson/github-action-markdown-link-check](https://github.com/gaurav-nelson/github-action-markdown-link-check) from 0.6.0 to 1.0.7. Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * docs: add sections to abci (#150) * spec: update abci events (#151) * spec: extract light-client to its own directory (#152) Co-authored-by: Callum Waters <cmwaters19@gmail.com> * spec: remove evidences (#153) * add a stale bot (#134) * Current versions of light client specs from tendermint-rs (#158) * current versions of light client specs from tendermint-rs * markdown lint * linting * links * links * links Co-authored-by: Marko Baricevic <marbar3778@yahoo.com> * Fastsync spec from tendermint-rs (#157) * fastsync spec from tendermint-rs * fixed broken link * fixed linting * more fixes * markdown lint * move fast_sync to rust-spec Co-authored-by: Marko Baricevic <marbar3778@yahoo.com> * Update README.md (#160) * spec/reactors/mempool: batch txs per peer (#155) * spec/reactors/mempool: batch txs per peer Refs https://github.com/tendermint/tendermint/issues/625 * update * spec: Light client attack detector (#164) * start with new detection and evidence spec * more definitions at top * sketch of functions * pre post draft * evidence proof * typo * evidence theory polished * some TODOs resolved * more TODOs * links * second to last revision before PR * links * I will read once more and then make a PR * removed peer handling definitions * secondary * ready to review * detector ready for review * Update rust-spec/lightclient/detection/detection.md Co-authored-by: Zarko Milosevic <zarko@informal.systems> * Update rust-spec/lightclient/detection/detection.md Co-authored-by: Zarko Milosevic <zarko@informal.systems> * Update rust-spec/lightclient/detection/detection.md Co-authored-by: Zarko Milosevic <zarko@informal.systems> * Update rust-spec/lightclient/detection/detection.md Co-authored-by: Zarko Milosevic <zarko@informal.systems> * Update rust-spec/lightclient/detection/detection.md Co-authored-by: Zarko Milosevic <zarko@informal.systems> * Update rust-spec/lightclient/detection/detection.md Co-authored-by: Zarko Milosevic <zarko@informal.systems> * Update rust-spec/lightclient/detection/detection.md * skip-trace * PossibleCommit explained * Update rust-spec/lightclient/detection/detection.md Co-authored-by: Zarko Milosevic <zarko@informal.systems> * comments by Zarko * renamed and changed link in README Co-authored-by: Zarko Milosevic <zarko@informal.systems> * fixed an overlooked conflict (#167) * describe valset sorting according to v0.34 requirements (#169) * evidence: update data structures (#165) * fix markdown linter (#172) * TLA+ specs from MBT revision (#173) * remove setOption (#181) * spec: protobuf changes (#156) Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com> * first check latest with secondary (#184) * Extending the blockchain specification (in the light client) to produce different ratios of faults (#183) * cleaning unused definitions * introduced the ratio of faulty processes * Update README.md (#185) * build(deps): bump gaurav-nelson/github-action-markdown-link-check from 1.0.7 to 1.0.8 (#188) Bumps [gaurav-nelson/github-action-markdown-link-check](https://github.com/gaurav-nelson/github-action-markdown-link-check) from 1.0.7 to 1.0.8. - [Release notes](https://github.com/gaurav-nelson/github-action-markdown-link-check/releases) - [Commits](https://github.com/gaurav-nelson/github-action-markdown-link-check/compare/1.0.7...e3c371c731b2f494f856dc5de7f61cea4d519907) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * spec: update light client verification to match supervisor (#171) * VDD renaming of verification spec + links fixed * latest() * backwards * added TODOs * link in old file to new name * better text * revision done. needs one more round of reading * renamed constants in 001 according to TLA+ and impl * ready for PR * forgot linting * Update rust-spec/lightclient/verification/verification_002_draft.md * Update rust-spec/lightclient/verification/verification_002_draft.md * added lightstore function needed for supervisor * added lightstore functions for supervisor * ident * Update rust-spec/lightclient/verification/verification_002_draft.md * github: issue template for proposals (#190) * Sequential Supervisor (#186) * move from tendermint-rs but needs discussion * markdown lint * TODO links replaced * links * links * links lint * Update rust-spec/lightclient/supervisor/supervisor.md * Update rust-spec/lightclient/supervisor/supervisor.md * Update rust-spec/lightclient/supervisor/supervisor.md * Update rust-spec/lightclient/supervisor/supervisor.md * moved peer handling definitions to supervisor * polishing * rename * Update rust-spec/lightclient/supervisor/supervisor_001_draft.md * Update rust-spec/lightclient/supervisor/supervisor_001_draft.md * changes to maintain StateVerified again * ready for changes in verification * start of supervisor * module name * fixed * more details * supevisor completed. Now I have to add function to verification * ready for review * tla comment * removed issues * Update rust-spec/lightclient/supervisor/supervisor_001_draft.md * intro text fixed * indentation * Update rust-spec/lightclient/supervisor/supervisor_001_draft.md * comment to entry points Co-authored-by: Marko Baricevic <marbar3778@yahoo.com> * RFC: adopt zip 215 (#144) Co-authored-by: Robert Zaremba <robert@zaremba.ch> * Core: move validation & data structures together (#176) Co-authored-by: Callum Waters <cmwaters19@gmail.com> * docs: make blockchain not viewable (#211) * evidence: update data structures to reflect added support of abci evidence (#213) * encoding: add secp, ref zip215, tables (#212) * Detector English Spec ready (#215) Add detector English spec * add Ivy proofs (#210) * add Ivy proofs * fix docker-compose command * Light client detector spec in TLA+ and refactoring of light client verification TLA+ spec (#216) Add light client detector spec in TLA+ * abci: lastcommitinfo.round extra sentence (#221) * abci: add abci_version to requestInfo (#223) * BFT requires _less than_ 1/3 faulty validators (#228) Thanks fo spotting the imprecision in the text, @shahankhatch ! * Draft of evidence handling for discussion (#225) * start with accountability deliverable * problem statement * draft function * quite complete draft. ready to discuss with Igor * Update isolate-attackers_001_draft.md * Update isolate-attackers_001_draft.md * Update isolate-attackers_001_draft.md * Update isolate-attackers_001_draft.md * Update isolate-attackers_001_draft.md * ready for TLA+ to take over * isolate * isolateamnesiatodos * Update isolate-attackers_001_draft.md * Update rust-spec/lightclient/attacks/isolate-attackers_001_draft.md Co-authored-by: Igor Konnov <konnov@forsyte.at> * Update rust-spec/lightclient/attacks/isolate-attackers_001_draft.md Co-authored-by: Igor Konnov <konnov@forsyte.at> * Update rust-spec/lightclient/attacks/isolate-attackers_001_draft.md Co-authored-by: Igor Konnov <konnov@forsyte.at> * Update rust-spec/lightclient/attacks/isolate-attackers_001_draft.md Co-authored-by: Igor Konnov <konnov@forsyte.at> * Update rust-spec/lightclient/attacks/isolate-attackers_001_draft.md Co-authored-by: Igor Konnov <konnov@forsyte.at> * Update rust-spec/lightclient/attacks/isolate-attackers_001_draft.md Co-authored-by: Igor Konnov <konnov@forsyte.at> * Update rust-spec/lightclient/attacks/isolate-attackers_001_draft.md Co-authored-by: Igor Konnov <konnov@forsyte.at> * Update rust-spec/lightclient/attacks/isolate-attackers_001_draft.md Co-authored-by: Igor Konnov <konnov@forsyte.at> * The TLA+ specification of the attackers detection (#231) * the working attackers isolation spec, needs more comments * the TLA+ spec of the attackers isolation * build(deps): bump gaurav-nelson/github-action-markdown-link-check (#233) Bumps [gaurav-nelson/github-action-markdown-link-check](https://github.com/gaurav-nelson/github-action-markdown-link-check) from 1.0.8 to 1.0.11. - [Release notes](https://github.com/gaurav-nelson/github-action-markdown-link-check/releases) - [Commits](https://github.com/gaurav-nelson/github-action-markdown-link-check/compare/1.0.8...2a60e0fe41b5361f446ccace6621a1a2a5c324cf) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Computing attack types (#232) Add light attack evidence handling * Update README.md (#234) * p2p: update frame size (#235) Reflect the change made in https://github.com/tendermint/tendermint/pull/5805 The MTU (Maximum Transmission Unit) for Ethernet is 1500 bytes. The IP header and the TCP header take up 20 bytes each at least (unless optional header fields are used) and thus the max for (non-Jumbo frame) Ethernet is 1500 - 20 -20 = 1460 Source: https://stackoverflow.com/a/3074427/820520 * build(deps): bump gaurav-nelson/github-action-markdown-link-check (#239) Bumps [gaurav-nelson/github-action-markdown-link-check](https://github.com/gaurav-nelson/github-action-markdown-link-check) from 1.0.11 to 1.0.12. - [Release notes](https://github.com/gaurav-nelson/github-action-markdown-link-check/releases) - [Commits](https://github.com/gaurav-nelson/github-action-markdown-link-check/compare/1.0.11...0fe4911067fa322422f325b002d2038ba5602170) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * layout: add section titles (#240) * reactors: remove bcv1 (#241) * abci: rewrite to proto interface (#237) * Update supervisor_001_draft.md (#243) * spec: remove reactor section (#242) Co-authored-by: Tess Rinearson <tess.rinearson@gmail.com> * non-critical bugfix in the TLA+ spec (found by new version of apalache) (#244) * params: remove block timeiota (#248) * proto: add files (#246) Co-authored-by: Erik Grinaker <erik@interchain.berlin> * proto: modify height int64 to uint64 (#253) * abci: note on concurrency (#258) Co-authored-by: Marko <marbar3778@yahoo.com> * spec: merge rust-spec (#252) * Fix list of RFCs (#266) * readme: cleanup (#262) * modify readme * add rfc and proto * add rust=spec back to avoid breakage * lint readme * genesis: Explain fields in genesis file (#270) * describe the genesis * Update spec/core/genesis.md Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Callum Waters <cmwaters19@gmail.com> * add wording on app_state * Update spec/core/genesis.md Co-authored-by: Callum Waters <cmwaters19@gmail.com> Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com> Co-authored-by: Callum Waters <cmwaters19@gmail.com> * p2p: links (#268) * fix links * fix more links * Proposer-based timestamp specification (#261) * added proposer-based timestamp spec * Update spec/consensus/proposer-based-timestamp/pbts_001_draft.md Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com> * Update spec/consensus/proposer-based-timestamp/pbts_001_draft.md Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com> * Update spec/consensus/proposer-based-timestamp/pbts-algorithm_001_draft.md Co-authored-by: Marko <marbar3778@yahoo.com> * Update spec/consensus/proposer-based-timestamp/pbts-algorithm_001_draft.md * Update spec/consensus/proposer-based-timestamp/pbts-sysmodel_001_draft.md Co-authored-by: Callum Waters <cmwaters19@gmail.com> * fixes from PR Co-authored-by: Josef Widder <44643235+josef-widder@users.noreply.github.com> Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com> Co-authored-by: Marko <marbar3778@yahoo.com> Co-authored-by: Callum Waters <cmwaters19@gmail.com> * abci: reorder sidebar (#282) * ABCI++ RFC (#254) * ABCI++ RFC This commit adds an RFC for ABCI++, which is a collection of three new phases of communication between the consensus engine and the application. Co-authored-by: Sunny Aggarwal <sunnya97@protonmail.ch> * Fix bugs pointed out by @liamsi * Update rfc/004-abci++.md Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> * Fix markdown lints * Update rfc/004-abci++.md Co-authored-by: Ismail Khoffi <Ismail.Khoffi@gmail.com> * Update rfc/004-abci++.md Co-authored-by: Tess Rinearson <tess.rinearson@gmail.com> * Update rfc/004-abci++.md Co-authored-by: Tess Rinearson <tess.rinearson@gmail.com> * Add information about the rename in the context section * Bold RFC * Add example for self-authenticating vote data * More exposition of the term IPC * Update pros / negatives * Fix sentence fragment * Add desc for no-ops Co-authored-by: Sunny Aggarwal <sunnya97@protonmail.ch> Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Ismail Khoffi <Ismail.Khoffi@gmail.com> Co-authored-by: Tess Rinearson <tess.rinearson@gmail.com> * RFC: ReverseSync - fetching historical data (#224) * core: update a few sections (#284) * p2p: update state sync messages for reverse sync (#285) * Update README.md (#286) * rpc: define spec for RPC (#276) * add rpc spec and support outline * add json * add more routes remove unneeded ones * add rest of rpc endpoints * add jsonrpc calls * add more jsonrpc calls * fix blockchain * cleanup unused links and add links to repos * Update spec/rpc/README.md Co-authored-by: Callum Waters <cmwaters19@gmail.com> * add missing param from consensus param * Update spec/rpc/README.md Co-authored-by: Callum Waters <cmwaters19@gmail.com> * Update spec/rpc/README.md Co-authored-by: Callum Waters <cmwaters19@gmail.com> * fix cast and add doc to readme Co-authored-by: Callum Waters <cmwaters19@gmail.com> Co-authored-by: Marko Baricevic <markobaricevic@Fergalicious.local> * A few improvements to the Ivy proof (#288) * Avoid quantifier alternation cycle The problematic quantifier alternation cycle arose because the definition of accountability_violation was unfolded. This commit also restructures the induction proof for clarity. * add count_lines.sh * fix typo and add forgotten complete=fo in comment Co-authored-by: Giuliano <giuliano@eic-61-11.galois.com> * Fixed a broken link (#291) * fix message type for block-sync (#298) * lint: fix lint errors (#301) * build(deps): bump actions/stale from 3 to 3.0.18 (#300) Bumps [actions/stale](https://github.com/actions/stale) from 3 to 3.0.18. - [Release notes](https://github.com/actions/stale/releases) - [Commits](https://github.com/actions/stale/compare/v3...v3.0.18) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump actions/stale from 3.0.18 to 3.0.19 (#302) Bumps [actions/stale](https://github.com/actions/stale) from 3.0.18 to 3.0.19. - [Release notes](https://github.com/actions/stale/releases) - [Commits](https://github.com/actions/stale/compare/v3.0.18...v3.0.19) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * rename HasVote to ReceivedVote (#289) * add a changelog to track changes (#303) * add a changelog to track changes * Update CHANGELOG.md Co-authored-by: Callum Waters <cmwaters19@gmail.com> Co-authored-by: Callum Waters <cmwaters19@gmail.com> * rpc: clarify timestamps (#304) * clarify timestamps * changelog entry * Update spec/rpc/README.md Co-authored-by: Callum Waters <cmwaters19@gmail.com> Co-authored-by: Callum Waters <cmwaters19@gmail.com> * rpc: add chunked genesis endpoint (#299) * rpc: add chunked genesis endpoint * fix lint * feedback * add info about error * fix lint Co-authored-by: marbar3778 <marbar3778@yahoo.com> * update ResponseCheckTx (#306) * rpc: Add totalGasUSed to block_results response (#308) * Add C++ code generation and test scenario (#310) * add parameters to byzantine send action * make net not trusted it's not necessary since for proofs Ivy will assume that the environment does not break action preconditions * use require instead of assume it seems that assume is not checked when other isolates call! * add comment * add comment * run with random seed * make domain model extractable to C++ * substitute require for assume assumes in an action are not checked when the action is called! I.e. they place no requirement on the caller; we're just assuming that the caller is going to do the right thing. This wasn't very important here but it leade to a minor inconsistency slipping through. * make the net isolate not trusted there was no need for it * add tendermint_test.ivy contains a simple test scenario that show that the specification is no vacuuous * update comment * add comments * throw if trying to parse nset value in the repl * add comment * minor refactoring * add new pex messages (#312) * build(deps): bump gaurav-nelson/github-action-markdown-link-check (#313) Bumps [gaurav-nelson/github-action-markdown-link-check](https://github.com/gaurav-nelson/github-action-markdown-link-check) from 1.0.12 to 1.0.13. - [Release notes](https://github.com/gaurav-nelson/github-action-markdown-link-check/releases) - [Commits](https://github.com/gaurav-nelson/github-action-markdown-link-check/compare/1.0.12...1.0.13) --- updated-dependencies: - dependency-name: gaurav-nelson/github-action-markdown-link-check dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * update spec to reference currently used timestamp type (#317) * build(deps): bump actions/stale from 3.0.19 to 4 (#319) Bumps [actions/stale](https://github.com/actions/stale) from 3.0.19 to 4. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/v3.0.19...v4) --- updated-dependencies: - dependency-name: actions/stale dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * address discrepancies between spec and implementation (#322) * update proto files for release (#318) * stale bot: ignore issues (#325) * evidence: add section explaining evidence (#324) * statesync: new messages for gossiping consensus params (#328) * rpc: update peer format in specification in NetInfo operation (#331) * Update supervisor_001_draft.md (#334) * core: text cleanup (#332) * abci: clarify what abci stands for (#336) * abci: clarify what abci stands for * link to abci type protos. * abci: clarify connection use in-process (#337) * abci: clarify connection use in-process * Update abci.md * Update spec/abci/abci.md Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * Update spec/abci/abci.md Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * invert abci explanations * lint++ * lint++ * lint++ * lint++ Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * proto: move proto files under the correct directory related to their package name (#344) * abci.md fixup (#339) * abci: points of clarification ahead of v0.1.0 * lint++ * typo * lint++ * double word score * grammar * Update spec/abci/abci.md Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * Update spec/abci/abci.md Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * Update spec/abci/abci.md Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * Update spec/abci/abci.md Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * Update spec/abci/abci.md Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * Update spec/abci/abci.md Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * Update spec/abci/abci.md Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * Update spec/abci/abci.md Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * Update spec/abci/abci.md Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * Update spec/abci/abci.md Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * Update spec/abci/abci.md Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * Update spec/abci/abci.md Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * Update spec/abci/abci.md Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * pr feedback * wip * update non-zero status code docs * fix event description * update CheckTx description Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * Update supervisor_001_draft.md (#333) * Update supervisor_001_draft.md If the only node in the *FullNodes* set is the primary, that was just deemed faulty, we can't find honest primary. * Update supervisor_001_draft.md * light: update initialization description (#320) * apps.md fixups (#341) * wip * wip * wip * remove comments in favor of gh comments * wip * udpates to language, should must etc * Apply suggestions from code review Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * remove tendermint cache description Co-authored-by: M. J. Fromberger <fromberger@interchain.io> * proto: add tendermint go changes (#349) * add missed proto files * add abci changes * rename blockchain to blocksync * Update proto/tendermint/abci/types.proto Co-authored-by: Callum Waters <cmwaters19@gmail.com> Co-authored-by: Callum Waters <cmwaters19@gmail.com> * fix mockery generation script (#9094) Signed-off-by: Marko Baricevic <marbar3778@yahoo.com> Co-authored-by: Milosevic, Zarko <zare.milosevic@gmail.com> Co-authored-by: Milosevic, Zarko <zare.milosevic@sicpa.com> Co-authored-by: Zarko Milosevic <zarko@tendermint.com> Co-authored-by: Marko <marbar3778@yahoo.com> Co-authored-by: Zarko Milosevic <zarko@interchain.io> Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com> Co-authored-by: Anca Zamfir <ancazamfir@users.noreply.github.com> Co-authored-by: dongsamb <dongsamb@gmail.com> Co-authored-by: Sunny Aggarwal <sunnya97@gmail.com> Co-authored-by: Anca Zamfir <anca@interchain.io> Co-authored-by: Ethan Buchman <ethan@coinculture.info> Co-authored-by: Zarko Milosevic <zarko@informal.systems> Co-authored-by: Ismail Khoffi <Ismail.Khoffi@gmail.com> Co-authored-by: Zaki Manian <zaki@tendermint.com> Co-authored-by: Erik Grinaker <erik@interchain.berlin> Co-authored-by: Tess Rinearson <tess.rinearson@gmail.com> Co-authored-by: Alexander Simmerl <a.simmerl@gmail.com> Co-authored-by: Igor Konnov <igor.konnov@gmail.com> Co-authored-by: Sean Braithwaite <brapse@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Josef Widder <44643235+josef-widder@users.noreply.github.com> Co-authored-by: Andrey Kuprianov <59489470+andrey-kuprianov@users.noreply.github.com> Co-authored-by: Igor Konnov <konnov@forsyte.at> Co-authored-by: Sam Hart <sam@hxrts.com> Co-authored-by: Robert Zaremba <robert@zaremba.ch> Co-authored-by: Giuliano <giuliano@losa.fr> Co-authored-by: Shahan Khatchadourian <shahan.k.code@gmail.com> Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com> Co-authored-by: istoilkovska <anili100@gmail.com> Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com> Co-authored-by: Sam Kleinman <garen@tychoish.com> Co-authored-by: Sunny Aggarwal <sunnya97@protonmail.ch> Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Marko Baricevic <markobaricevic@Fergalicious.local> Co-authored-by: Giuliano <giuliano@eic-61-11.galois.com> Co-authored-by: Jordan Sexton <jordan@jordansexton.com> Co-authored-by: MengXiangJian <805442788@qq.com> Co-authored-by: Yixin Luo <18810541851@163.com> Co-authored-by: crypto-facs <84574577+crypto-facs@users.noreply.github.com> Co-authored-by: Giuliano <giuliano@galois.com> Co-authored-by: William Banfield <4561443+williambanfield@users.noreply.github.com> Co-authored-by: Mateusz Górski <goral09@users.noreply.github.com> Co-authored-by: M. J. Fromberger <fromberger@interchain.io> Co-authored-by: Thane Thomson <connect@thanethomson.com>
30 KiB
order, title
| order | title |
|---|---|
| 2 | Applications |
Applications
Please ensure you've first read the spec for ABCI Methods and Types
Here we cover the following components of ABCI applications:
- Connection State - the interplay between ABCI connections and application state
and the differences between
CheckTxandDeliverTx. - Transaction Results - rules around transaction results and validity
- Validator Set Updates - how validator sets are
changed during
InitChainandEndBlock - Query - standards for using the
Querymethod and proofs about the application state - Crash Recovery - handshake protocol to synchronize Tendermint and the application on startup.
- State Sync - rapid bootstrapping of new nodes by restoring state machine snapshots
Connection State
Since Tendermint maintains four concurrent ABCI connections, it is typical
for an application to maintain a distinct state for each, and for the states to
be synchronized during Commit.
Concurrency
In principle, each of the four ABCI connections operate concurrently with one
another. This means applications need to ensure access to state is
thread safe. In practice, both the
default in-process ABCI client
and the
default Go ABCI
server
use global locks across all connections, so they are not
concurrent at all. This means if your app is written in Go, and compiled in-process with Tendermint
using the default NewLocalClient, or run out-of-process using the default SocketServer,
ABCI messages from all connections will be linearizable (received one at a
time).
The existence of this global mutex means Go application developers can get thread safety for application state by routing all reads and writes through the ABCI system. Thus it may be unsafe to expose application state directly to an RPC interface, and unless explicit measures are taken, all queries should be routed through the ABCI Query method.
BeginBlock
The BeginBlock request can be used to run some code at the beginning of every block. It also allows Tendermint to send the current block hash and header to the application, before it sends any of the transactions.
The app should remember the latest height and header (ie. from which it has run a successful Commit) so that it can tell Tendermint where to pick up from when it restarts. See information on the Handshake, below.
Commit
Application state should only be persisted to disk during Commit.
Before Commit is called, Tendermint locks and flushes the mempool so that no new messages will
be received on the mempool connection. This provides an opportunity to safely update all four connection
states to the latest committed state at once.
When Commit completes, it unlocks the mempool.
WARNING: if the ABCI app logic processing the Commit message sends a
/broadcast_tx_sync or /broadcast_tx_commit and waits for the response
before proceeding, it will deadlock. Executing those broadcast_tx calls
involves acquiring a lock that is held during the Commit call, so it's not
possible. If you make the call to the broadcast_tx endpoints concurrently,
that's no problem, it just can't be part of the sequential logic of the
Commit function.
Consensus Connection
The Consensus Connection should maintain a DeliverTxState - the working state
for block execution. It should be updated by the calls to BeginBlock, DeliverTx,
and EndBlock during block execution and committed to disk as the "latest
committed state" during Commit.
Updates made to the DeliverTxState by each method call must be readable by each subsequent method -
ie. the updates are linearizable.
Mempool Connection
The mempool Connection should maintain a CheckTxState
to sequentially process pending transactions in the mempool that have
not yet been committed. It should be initialized to the latest committed state
at the end of every Commit.
Before calling Commit, Tendermint will lock and flush the mempool connection,
ensuring that all existing CheckTx are responded to and no new ones can begin.
The CheckTxState may be updated concurrently with the DeliverTxState, as
messages may be sent concurrently on the Consensus and Mempool connections.
After Commit, while still holding the mempool lock, CheckTx is run again on all transactions that remain in the
node's local mempool after filtering those included in the block.
An additional Type parameter is made available to the CheckTx function that
indicates whether an incoming transaction is new (CheckTxType_New), or a
recheck (CheckTxType_Recheck).
Finally, after re-checking transactions in the mempool, Tendermint will unlock the mempool connection. New transactions are once again able to be processed through CheckTx.
Note that CheckTx is just a weak filter to keep invalid transactions out of the block chain. CheckTx doesn't have to check everything that affects transaction validity; the expensive things can be skipped. It's weak because a Byzantine node doesn't care about CheckTx; it can propose a block full of invalid transactions if it wants.
Replay Protection
To prevent old transactions from being replayed, CheckTx must implement replay protection.
It is possible for old transactions to be sent to the application. So it is important CheckTx implements some logic to handle them.
Query Connection
The Info Connection should maintain a QueryState for answering queries from the user,
and for initialization when Tendermint first starts up (both described further
below).
It should always contain the latest committed state associated with the
latest committed block.
QueryState should be set to the latest DeliverTxState at the end of every Commit,
after the full block has been processed and the state committed to disk.
Otherwise it should never be modified.
Tendermint Core currently uses the Query connection to filter peers upon connecting, according to IP address or node ID. For instance, returning non-OK ABCI response to either of the following queries will cause Tendermint to not connect to the corresponding peer:
p2p/filter/addr/<ip addr>, where<ip addr>is an IP address.p2p/filter/id/<id>, where<is>is the hex-encoded node ID (the hash of the node's p2p pubkey).
Note: these query formats are subject to change!
Snapshot Connection
The Snapshot Connection is optional, and is only used to serve state sync snapshots for other nodes and/or restore state sync snapshots to a local node being bootstrapped.
For more information, see the state sync section of this document.
Transaction Results
The Info and Log fields are non-deterministic values for debugging/convenience purposes
that are otherwise ignored.
The Data field must be strictly deterministic, but can be arbitrary data.
Gas
Ethereum introduced the notion of gas as an abstract representation of the
cost of resources used by nodes when processing transactions. Every operation in the
Ethereum Virtual Machine uses some amount of gas, and gas can be accepted at a market-variable price.
Users propose a maximum amount of gas for their transaction; if the tx uses less, they get
the difference credited back. Tendermint adopts a similar abstraction,
though uses it only optionally and weakly, allowing applications to define
their own sense of the cost of execution.
In Tendermint, the ConsensusParams.Block.MaxGas limits the amount of gas that can be used in a block.
The default value is -1, meaning no limit, or that the concept of gas is
meaningless.
Responses contain a GasWanted and GasUsed field. The former is the maximum
amount of gas the sender of a tx is willing to use, and the later is how much it actually
used. Applications should enforce that GasUsed <= GasWanted - ie. tx execution
should halt before it can use more resources than it requested.
When MaxGas > -1, Tendermint enforces the following rules:
GasWanted <= MaxGasfor all txs in the mempool(sum of GasWanted in a block) <= MaxGaswhen proposing a block
If MaxGas == -1, no rules about gas are enforced.
Note that Tendermint does not currently enforce anything about Gas in the consensus, only the mempool. This means it does not guarantee that committed blocks satisfy these rules! It is the application's responsibility to return non-zero response codes when gas limits are exceeded.
The GasUsed field is ignored completely by Tendermint. That said, applications should enforce:
GasUsed <= GasWantedfor any given transaction(sum of GasUsed in a block) <= MaxGasfor every block
In the future, we intend to add a Priority field to the responses that can be
used to explicitly prioritize txs in the mempool for inclusion in a block
proposal. See #1861.
CheckTx
If Code != 0, it will be rejected from the mempool and hence
not broadcasted to other peers and not included in a proposal block.
Data contains the result of the CheckTx transaction execution, if any. It is
semantically meaningless to Tendermint.
Events include any events for the execution, though since the transaction has not
been committed yet, they are effectively ignored by Tendermint.
DeliverTx
DeliverTx is the workhorse of the blockchain. Tendermint sends the DeliverTx requests asynchronously but in order, and relies on the underlying socket protocol (ie. TCP) to ensure they are received by the app in order. They have already been ordered in the global consensus by the Tendermint protocol.
If DeliverTx returns Code != 0, the transaction will be considered invalid,
though it is still included in the block.
DeliverTx also returns a Code, Data, and Log.
Data contains the result of the CheckTx transaction execution, if any. It is
semantically meaningless to Tendermint.
Both the Code and Data are included in a structure that is hashed into the
LastResultsHash of the next block header.
Events include any events for the execution, which Tendermint will use to index
the transaction by. This allows transactions to be queried according to what
events took place during their execution.
Updating the Validator Set
The application may set the validator set during InitChain, and may update it during EndBlock.
Note that the maximum total power of the validator set is bounded by
MaxTotalVotingPower = MaxInt64 / 8. Applications are responsible for ensuring
they do not make changes to the validator set that cause it to exceed this
limit.
Additionally, applications must ensure that a single set of updates does not contain any duplicates - a given public key can only appear once within a given update. If an update includes duplicates, the block execution will fail irrecoverably.
InitChain
The InitChain method can return a list of validators.
If the list is empty, Tendermint will use the validators loaded in the genesis
file.
If the list returned by InitChain is not empty, Tendermint will use its contents as the validator set.
This way the application can set the initial validator set for the
blockchain.
EndBlock
Updates to the Tendermint validator set can be made by returning
ValidatorUpdate objects in the ResponseEndBlock:
message ValidatorUpdate {
tendermint.crypto.keys.PublicKey pub_key
int64 power
}
message PublicKey {
oneof {
ed25519 bytes = 1;
}
The pub_key currently supports only one type:
type = "ed25519"
The power is the new voting power for the validator, with the
following rules:
- power must be non-negative
- if power is 0, the validator must already exist, and will be removed from the validator set
- if power is non-0:
- if the validator does not already exist, it will be added to the validator set with the given power
- if the validator does already exist, its power will be adjusted to the given power
- the total power of the new validator set must not exceed MaxTotalVotingPower
Note the updates returned in block H will only take effect at block H+2.
Consensus Parameters
ConsensusParams enforce certain limits in the blockchain, like the maximum size of blocks, amount of gas used in a block, and the maximum acceptable age of evidence. They can be set in InitChain and updated in EndBlock.
BlockParams.MaxBytes
The maximum size of a complete Protobuf encoded block. This is enforced by Tendermint consensus.
This implies a maximum transaction size that is this MaxBytes, less the expected size of the header, the validator set, and any included evidence in the block.
Must have 0 < MaxBytes < 100 MB.
BlockParams.MaxGas
The maximum of the sum of GasWanted that will be allowed in a proposed block.
This is not enforced by Tendermint consensus.
It is left to the app to enforce (ie. if txs are included past the
limit, they should return non-zero codes). It is used by Tendermint to limit the
txs included in a proposed block.
Must have MaxGas >= -1.
If MaxGas == -1, no limit is enforced.
EvidenceParams.MaxAgeDuration
This is the maximum age of evidence in time units. This is enforced by Tendermint consensus.
If a block includes evidence older than this (AND the evidence was created more
than MaxAgeNumBlocks ago), the block will be rejected (validators won't vote
for it).
Must have MaxAgeDuration > 0.
EvidenceParams.MaxAgeNumBlocks
This is the maximum age of evidence in blocks. This is enforced by Tendermint consensus.
If a block includes evidence older than this (AND the evidence was created more
than MaxAgeDuration ago), the block will be rejected (validators won't vote
for it).
Must have MaxAgeNumBlocks > 0.
EvidenceParams.MaxNum
This is the maximum number of evidence that can be committed to a single block.
The product of this and the MaxEvidenceBytes must not exceed the size of
a block minus it's overhead ( ~ MaxBytes).
Must have MaxNum > 0.
Updates
The application may set the ConsensusParams during InitChain, and update them during EndBlock. If the ConsensusParams is empty, it will be ignored. Each field that is not empty will be applied in full. For instance, if updating the Block.MaxBytes, applications must also set the other Block fields (like Block.MaxGas), even if they are unchanged, as they will otherwise cause the value to be updated to 0.
InitChain
ResponseInitChain includes a ConsensusParams. If ConsensusParams is nil, Tendermint will use the params loaded in the genesis file. If ConsensusParams is not nil, Tendermint will use it. This way the application can determine the initial consensus params for the blockchain.
EndBlock
ResponseEndBlock includes a ConsensusParams. If ConsensusParams nil, Tendermint will do nothing. If ConsensusParam is not nil, Tendermint will use it. This way the application can update the consensus params over time.
Note the updates returned in block H will take effect right away for block
H+1.
Query
Query is a generic method with lots of flexibility to enable diverse sets of queries on application state. Tendermint makes use of Query to filter new peers based on ID and IP, and exposes Query to the user over RPC.
Note that calls to Query are not replicated across nodes, but rather query the local node's state - hence they may return stale reads. For reads that require consensus, use a transaction.
The most important use of Query is to return Merkle proofs of the application state at some height that can be used for efficient application-specific light-clients.
Note Tendermint has technically no requirements from the Query message for normal operation - that is, the ABCI app developer need not implement Query functionality if they do not wish too.
Query Proofs
The Tendermint block header includes a number of hashes, each providing an
anchor for some type of proof about the blockchain. The ValidatorsHash enables
quick verification of the validator set, the DataHash gives quick
verification of the transactions included in the block, etc.
The AppHash is unique in that it is application specific, and allows for
application-specific Merkle proofs about the state of the application.
While some applications keep all relevant state in the transactions themselves
(like Bitcoin and its UTXOs), others maintain a separated state that is
computed deterministically from transactions, but is not contained directly in
the transactions themselves (like Ethereum contracts and accounts).
For such applications, the AppHash provides a much more efficient way to verify light-client proofs.
ABCI applications can take advantage of more efficient light-client proofs for their state as follows:
- return the Merkle root of the deterministic application state in
ResponseCommit.Data. This Merkle root will be included as theAppHashin the next block. - return efficient Merkle proofs about that application state in
ResponseQuery.Proofthat can be verified using theAppHashof the corresponding block.
For instance, this allows an application's light-client to verify proofs of absence in the application state, something which is much less efficient to do using the block hash.
Some applications (eg. Ethereum, Cosmos-SDK) have multiple "levels" of Merkle trees,
where the leaves of one tree are the root hashes of others. To support this, and
the general variability in Merkle proofs, the ResponseQuery.Proof has some minimal structure:
message ProofOps {
repeated ProofOp ops
}
message ProofOp {
string type = 1;
bytes key = 2;
bytes data = 3;
}
Each ProofOp contains a proof for a single key in a single Merkle tree, of the specified type.
This allows ABCI to support many different kinds of Merkle trees, encoding
formats, and proofs (eg. of presence and absence) just by varying the type.
The data contains the actual encoded proof, encoded according to the type.
When verifying the full proof, the root hash for one ProofOp is the value being
verified for the next ProofOp in the list. The root hash of the final ProofOp in
the list should match the AppHash being verified against.
Peer Filtering
When Tendermint connects to a peer, it sends two queries to the ABCI application using the following paths, with no additional data:
/p2p/filter/addr/<IP:PORT>, where<IP:PORT>denote the IP address and the port of the connectionp2p/filter/id/<ID>, where<ID>is the peer node ID (ie. the pubkey.Address() for the peer's PubKey)
If either of these queries return a non-zero ABCI code, Tendermint will refuse to connect to the peer.
Paths
Queries are directed at paths, and may optionally include additional data.
The expectation is for there to be some number of high level paths
differentiating concerns, like /p2p, /store, and /app. Currently,
Tendermint only uses /p2p, for filtering peers. For more advanced use, see the
implementation of
Query in the Cosmos-SDK.
Crash Recovery
On startup, Tendermint calls the Info method on the Info Connection to get the latest
committed state of the app. The app MUST return information consistent with the
last block it succesfully completed Commit for.
If the app succesfully committed block H, then last_block_height = H and last_block_app_hash = <hash returned by Commit for block H>. If the app
failed during the Commit of block H, then last_block_height = H-1 and
last_block_app_hash = <hash returned by Commit for block H-1, which is the hash in the header of block H>.
We now distinguish three heights, and describe how Tendermint syncs itself with the app.
storeBlockHeight = height of the last block Tendermint saw a commit for
stateBlockHeight = height of the last block for which Tendermint completed all
block processing and saved all ABCI results to disk
appBlockHeight = height of the last block for which ABCI app succesfully
completed Commit
Note we always have storeBlockHeight >= stateBlockHeight and storeBlockHeight >= appBlockHeight
Note also Tendermint never calls Commit on an ABCI app twice for the same height.
The procedure is as follows.
First, some simple start conditions:
If appBlockHeight == 0, then call InitChain.
If storeBlockHeight == 0, we're done.
Now, some sanity checks:
If storeBlockHeight < appBlockHeight, error
If storeBlockHeight < stateBlockHeight, panic
If storeBlockHeight > stateBlockHeight+1, panic
Now, the meat:
If storeBlockHeight == stateBlockHeight && appBlockHeight < storeBlockHeight,
replay all blocks in full from appBlockHeight to storeBlockHeight.
This happens if we completed processing the block, but the app forgot its height.
If storeBlockHeight == stateBlockHeight && appBlockHeight == storeBlockHeight, we're done.
This happens if we crashed at an opportune spot.
If storeBlockHeight == stateBlockHeight+1
This happens if we started processing the block but didn't finish.
If appBlockHeight < stateBlockHeight
replay all blocks in full from appBlockHeight to storeBlockHeight-1,
and replay the block at storeBlockHeight using the WAL.
This happens if the app forgot the last block it committed.
If appBlockHeight == stateBlockHeight,
replay the last block (storeBlockHeight) in full.
This happens if we crashed before the app finished Commit
If appBlockHeight == storeBlockHeight
update the state using the saved ABCI responses but dont run the block against the real app.
This happens if we crashed after the app finished Commit but before Tendermint saved the state.
State Sync
A new node joining the network can simply join consensus at the genesis height and replay all historical blocks until it is caught up. However, for large chains this can take a significant amount of time, often on the order of days or weeks.
State sync is an alternative mechanism for bootstrapping a new node, where it fetches a snapshot of the state machine at a given height and restores it. Depending on the application, this can be several orders of magnitude faster than replaying blocks.
Note that state sync does not currently backfill historical blocks, so the node will have a truncated block history - users are advised to consider the broader network implications of this in terms of block availability and auditability. This functionality may be added in the future.
For details on the specific ABCI calls and types, see the methods and types section.
Taking Snapshots
Applications that want to support state syncing must take state snapshots at regular intervals. How this is accomplished is entirely up to the application. A snapshot consists of some metadata and a set of binary chunks in an arbitrary format:
-
Height (uint64): The height at which the snapshot is taken. It must be taken after the given height has been committed, and must not contain data from any later heights. -
Format (uint32): An arbitrary snapshot format identifier. This can be used to version snapshot formats, e.g. to switch from Protobuf to MessagePack for serialization. The application can use this when restoring to choose whether to accept or reject a snapshot. -
Chunks (uint32): The number of chunks in the snapshot. Each chunk contains arbitrary binary data, and should be less than 16 MB; 10 MB is a good starting point. -
Hash ([]byte): An arbitrary hash of the snapshot. This is used to check whether a snapshot is the same across nodes when downloading chunks. -
Metadata ([]byte): Arbitrary snapshot metadata, e.g. chunk hashes for verification or any other necessary info.
For a snapshot to be considered the same across nodes, all of these fields must be identical. When sent across the network, snapshot metadata messages are limited to 4 MB.
When a new node is running state sync and discovering snapshots, Tendermint will query an existing
application via the ABCI ListSnapshots method to discover available snapshots, and load binary
snapshot chunks via LoadSnapshotChunk. The application is free to choose how to implement this
and which formats to use, but must provide the following guarantees:
-
Consistent: A snapshot must be taken at a single isolated height, unaffected by concurrent writes. This can be accomplished by using a data store that supports ACID transactions with snapshot isolation.
-
Asynchronous: Taking a snapshot can be time-consuming, so it must not halt chain progress, for example by running in a separate thread.
-
Deterministic: A snapshot taken at the same height in the same format must be identical (at the byte level) across nodes, including all metadata. This ensures good availability of chunks, and that they fit together across nodes.
A very basic approach might be to use a datastore with MVCC transactions (such as RocksDB), start a transaction immediately after block commit, and spawn a new thread which is passed the transaction handle. This thread can then export all data items, serialize them using e.g. Protobuf, hash the byte stream, split it into chunks, and store the chunks in the file system along with some metadata - all while the blockchain is applying new blocks in parallel.
A more advanced approach might include incremental verification of individual chunks against the chain app hash, parallel or batched exports, compression, and so on.
Old snapshots should be removed after some time - generally only the last two snapshots are needed (to prevent the last one from being removed while a node is restoring it).
Bootstrapping a Node
An empty node can be state synced by setting the configuration option statesync.enabled = true. The node also needs the chain genesis file for basic chain info, and configuration for
light client verification of the restored snapshot: a set of Tendermint RPC servers, and a
trusted header hash and corresponding height from a trusted source, via the statesync
configuration section.
Once started, the node will connect to the P2P network and begin discovering snapshots. These
will be offered to the local application via the OfferSnapshot ABCI method. Once a snapshot
is accepted Tendermint will fetch and apply the snapshot chunks. After all chunks have been
successfully applied, Tendermint verifies the app's AppHash against the chain using the light
client, then switches the node to normal consensus operation.
Snapshot Discovery
When the empty node join the P2P network, it asks all peers to report snapshots via the
ListSnapshots ABCI call (limited to 10 per node). After some time, the node picks the most
suitable snapshot (generally prioritized by height, format, and number of peers), and offers it
to the application via OfferSnapshot. The application can choose a number of responses,
including accepting or rejecting it, rejecting the offered format, rejecting the peer who sent
it, and so on. Tendermint will keep discovering and offering snapshots until one is accepted or
the application aborts.
Snapshot Restoration
Once a snapshot has been accepted via OfferSnapshot, Tendermint begins downloading chunks from
any peers that have the same snapshot (i.e. that have identical metadata fields). Chunks are
spooled in a temporary directory, and then given to the application in sequential order via
ApplySnapshotChunk until all chunks have been accepted.
The method for restoring snapshot chunks is entirely up to the application.
During restoration, the application can respond to ApplySnapshotChunk with instructions for how
to continue. This will typically be to accept the chunk and await the next one, but it can also
ask for chunks to be refetched (either the current one or any number of previous ones), P2P peers
to be banned, snapshots to be rejected or retried, and a number of other responses - see the ABCI
reference for details.
If Tendermint fails to fetch a chunk after some time, it will reject the snapshot and try a
different one via OfferSnapshot - the application can choose whether it wants to support
restarting restoration, or simply abort with an error.
Snapshot Verification
Once all chunks have been accepted, Tendermint issues an Info ABCI call to retrieve the
LastBlockAppHash. This is compared with the trusted app hash from the chain, retrieved and
verified using the light client. Tendermint also checks that LastBlockHeight corresponds to the
height of the snapshot.
This verification ensures that an application is valid before joining the network. However, the snapshot restoration may take a long time to complete, so applications may want to employ additional verification during the restore to detect failures early. This might e.g. include incremental verification of each chunk against the app hash (using bundled Merkle proofs), checksums to protect against data corruption by the disk or network, and so on. However, it is important to note that the only trusted information available is the app hash, and all other snapshot metadata can be spoofed by adversaries.
Apps may also want to consider state sync denial-of-service vectors, where adversaries provide invalid or harmful snapshots to prevent nodes from joining the network. The application can counteract this by asking Tendermint to ban peers. As a last resort, node operators can use P2P configuration options to whitelist a set of trusted peers that can provide valid snapshots.
Transition to Consensus
Once the snapshots have all been restored, Tendermint gathers additional information necessary for
bootstrapping the node (e.g. chain ID, consensus parameters, validator sets, and block headers)
from the genesis file and light client RPC servers. It also fetches and records the AppVersion
from the ABCI application.
Once the state machine has been restored and Tendermint has gathered this additional information, it transitions to block sync (if enabled) to fetch any remaining blocks up the chain head, and then transitions to regular consensus operation. At this point the node operates like any other node, apart from having a truncated block history at the height of the restored snapshot.