├── rfc
├── images
│ ├── abci++.png
│ ├── abci.png
│ └── block-retention.png
├── rfc_template.md
├── README.md
├── 003-ed25519-verification.md
└── 002-nonzero-genesis.md
├── spec
├── p2p
│ ├── readme.md
│ ├── messages
│ │ ├── evidence.md
│ │ ├── README.md
│ │ ├── mempool.md
│ │ ├── pex.md
│ │ └── block-sync.md
│ ├── config.md
│ ├── node.md
│ └── connection.md
├── blockchain
│ ├── state.md
│ ├── encoding.md
│ ├── blockchain.md
│ └── readme.md
├── light-client
│ ├── experiments.png
│ ├── assets
│ │ └── light-node-image.png
│ ├── detection
│ │ ├── 005bmc-apalache-error.csv
│ │ ├── 004bmc-apalache-ok.csv
│ │ ├── LCD_MC3_3_faulty.tla
│ │ ├── LCD_MC3_4_faulty.tla
│ │ ├── LCD_MC4_4_faulty.tla
│ │ ├── LCD_MC5_5_faulty.tla
│ │ └── README.md
│ ├── verification
│ │ ├── 005bmc-apalache-error.csv
│ │ ├── 004bmc-apalache-ok.csv
│ │ ├── MC5_5_faulty.tla
│ │ ├── MC4_4_correct.tla
│ │ ├── MC4_5_correct.tla
│ │ ├── MC4_5_faulty.tla
│ │ ├── MC4_6_faulty.tla
│ │ ├── MC4_7_faulty.tla
│ │ ├── MC4_3_correct.tla
│ │ ├── MC4_3_faulty.tla
│ │ ├── MC4_4_faulty.tla
│ │ ├── MC5_7_faulty.tla
│ │ ├── MC5_5_correct.tla
│ │ ├── MC4_4_correct_drifted.tla
│ │ ├── MC4_4_faulty_drifted.tla
│ │ ├── MC7_5_faulty.tla
│ │ ├── MC7_7_faulty.tla
│ │ ├── MC5_5_faulty_peer_two_thirds_faulty.tla
│ │ ├── MC5_5_correct_peer_two_thirds_faulty.tla
│ │ ├── verification_003_draft.md
│ │ ├── 003bmc-apalache-error.csv
│ │ ├── 001bmc-apalache.csv
│ │ └── 002bmc-apalache-ok.csv
│ ├── accountability
│ │ ├── run.sh
│ │ ├── results
│ │ │ ├── 001indinv-apalache-unstable.csv
│ │ │ └── 001indinv-apalache-report.md
│ │ ├── typedefs.tla
│ │ ├── 001indinv-apalache.csv
│ │ ├── TendermintAccTrace_004_draft.tla
│ │ ├── MC_n4_f1.tla
│ │ ├── MC_n4_f2.tla
│ │ ├── MC_n4_f3.tla
│ │ ├── MC_n5_f1.tla
│ │ ├── MC_n5_f2.tla
│ │ ├── MC_n6_f1.tla
│ │ ├── MC_n4_f2_amnesia.tla
│ │ ├── Synopsis.md
│ │ └── TendermintAccDebug_004_draft.tla
│ ├── attacks
│ │ └── MC_5_3.tla
│ └── supervisor
│ │ ├── supervisor_001_draft.tla
│ │ └── supervisor_002_draft.md
├── consensus
│ ├── light-client
│ │ ├── detection.md
│ │ ├── assets
│ │ │ └── light-node-image.png
│ │ ├── verification.md
│ │ ├── accountability.md
│ │ └── README.md
│ ├── consensus-paper
│ │ ├── README.md
│ │ ├── homodel.sty
│ │ ├── conclusion.tex
│ │ ├── rounddiag.sty
│ │ ├── technote.sty
│ │ └── latex8.sty
│ ├── proposer-based-timestamp
│ │ └── tla
│ │ │ └── typedefs.tla
│ ├── readme.md
│ ├── wal.md
│ ├── creating-proposal.md
│ └── bft-time.md
├── core
│ ├── readme.md
│ ├── genesis.md
│ └── state.md
├── abci
│ ├── README.md
│ └── client-server.md
├── abci++
│ ├── README.md
│ ├── v0.md
│ └── v1.md
└── README.md
├── .gitignore
├── ivy-proofs
├── output
│ └── .gitignore
├── docker-compose.yml
├── count_lines.sh
├── check_proofs.sh
├── Dockerfile
├── README.md
├── accountable_safety_2.ivy
├── classic_safety.ivy
├── network_shim.ivy
└── tendermint_test.ivy
├── rust-spec
├── lightclient
│ ├── README.md
│ └── verification
│ │ └── README.md
└── fastsync
│ └── README.md
├── .github
├── CODEOWNERS
├── dependabot.yml
├── workflows
│ ├── action.yml
│ ├── stale.yml
│ ├── proto-check.yml
│ ├── linter.yml
│ └── proto-dockerfile.yml
└── ISSUE_TEMPLATE
│ └── proposal.md
├── proto
├── tendermint
│ ├── libs
│ │ └── bits
│ │ │ └── types.proto
│ ├── mempool
│ │ └── types.proto
│ ├── crypto
│ │ ├── keys.proto
│ │ └── proof.proto
│ ├── version
│ │ └── types.proto
│ ├── types
│ │ ├── block.proto
│ │ ├── validator.proto
│ │ └── evidence.proto
│ ├── p2p
│ │ ├── pex.proto
│ │ ├── conn.proto
│ │ └── types.proto
│ ├── blocksync
│ │ └── types.proto
│ ├── statesync
│ │ └── types.proto
│ └── consensus
│ │ └── types.proto
├── Dockerfile
└── README.md
├── .markdownlint.yml
├── buf.yaml
├── .clang-format
├── CHANGELOG.md
├── buf.gen.yaml
├── Makefile
└── README.md
/rfc/images/abci++.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tendermint/spec/HEAD/rfc/images/abci++.png
--------------------------------------------------------------------------------
/rfc/images/abci.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tendermint/spec/HEAD/rfc/images/abci.png
--------------------------------------------------------------------------------
/spec/p2p/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | parent:
4 | title: P2P
5 | order: 6
6 | ---
7 |
--------------------------------------------------------------------------------
/spec/blockchain/state.md:
--------------------------------------------------------------------------------
1 | # State
2 |
3 | Deprecated see [core/state.md](../core/state.md)
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.aux
2 | *.bbl
3 | *.blg
4 | *.log
5 | *.pdf
6 | *.gz
7 | *.dvi
8 | .idea
9 | *.pb.go
10 |
--------------------------------------------------------------------------------
/rfc/images/block-retention.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tendermint/spec/HEAD/rfc/images/block-retention.png
--------------------------------------------------------------------------------
/spec/blockchain/encoding.md:
--------------------------------------------------------------------------------
1 | # Encoding
2 |
3 | Deprecated see [core/data_structures.md](../core/encoding.md)
4 |
--------------------------------------------------------------------------------
/ivy-proofs/output/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore everything in this directory
2 | *
3 | # Except this file
4 | !.gitignore
5 |
--------------------------------------------------------------------------------
/spec/light-client/experiments.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tendermint/spec/HEAD/spec/light-client/experiments.png
--------------------------------------------------------------------------------
/rust-spec/lightclient/README.md:
--------------------------------------------------------------------------------
1 | # Light Clients
2 |
3 | Deprecated see [spec/light-client](../../spec/light-client)
4 |
--------------------------------------------------------------------------------
/spec/blockchain/blockchain.md:
--------------------------------------------------------------------------------
1 | # Blockchain
2 |
3 | Deprecated see [core/data_structures.md](../core/data_structures.md)
4 |
--------------------------------------------------------------------------------
/spec/light-client/assets/light-node-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tendermint/spec/HEAD/spec/light-client/assets/light-node-image.png
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # CODEOWNERS: https://help.github.com/articles/about-codeowners/
2 |
3 | * @milosevic @ebuchman @josef-widder @konnov
4 |
--------------------------------------------------------------------------------
/spec/consensus/light-client/detection.md:
--------------------------------------------------------------------------------
1 | # Detection
2 |
3 | Deprecated, please see [light-client/detection](../../light-client/detection/README.md).
4 |
--------------------------------------------------------------------------------
/spec/consensus/light-client/assets/light-node-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tendermint/spec/HEAD/spec/consensus/light-client/assets/light-node-image.png
--------------------------------------------------------------------------------
/rust-spec/lightclient/verification/README.md:
--------------------------------------------------------------------------------
1 | # Verification
2 |
3 | Deprecated see [spec/light-client/verification](../../../spec/light-client/verification/README.md)
4 |
--------------------------------------------------------------------------------
/spec/consensus/light-client/verification.md:
--------------------------------------------------------------------------------
1 | # Core Verification
2 |
3 | Deprecated, please see [light-client/accountability](../../light-client/verification/README.md).
4 |
--------------------------------------------------------------------------------
/spec/consensus/light-client/accountability.md:
--------------------------------------------------------------------------------
1 | # Fork accountability
2 |
3 | Deprecated, please see [light-client/accountability](../../light-client/accountability/README.md).
4 |
--------------------------------------------------------------------------------
/proto/tendermint/libs/bits/types.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package tendermint.libs.bits;
3 |
4 | message BitArray {
5 | int64 bits = 1;
6 | repeated uint64 elems = 2;
7 | }
8 |
--------------------------------------------------------------------------------
/rust-spec/fastsync/README.md:
--------------------------------------------------------------------------------
1 | # Fast Sync
2 |
3 | Deprecated see [tendermint/docs/tendermint-core/block-sync](https://github.com/tendermint/tendermint/blob/master/docs/tendermint-core/block-sync/README.md)
4 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: github-actions
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | time: "11:00"
8 | open-pull-requests-limit: 10
9 |
--------------------------------------------------------------------------------
/ivy-proofs/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | tendermint-proof:
4 | build: .
5 | volumes:
6 | - ./:/home/user/tendermint-proof:ro
7 | - ./output:/home/user/tendermint-proof/output:rw
8 |
9 |
--------------------------------------------------------------------------------
/.markdownlint.yml:
--------------------------------------------------------------------------------
1 | default: true
2 | MD001: false
3 | MD007: { indent: 4 }
4 | MD013: false
5 | MD024: { siblings_only: true }
6 | MD025: false
7 | MD033: false
8 | MD036: false
9 | MD010: false
10 | MD012: false
11 | MD028: false
12 |
--------------------------------------------------------------------------------
/proto/tendermint/mempool/types.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package tendermint.mempool;
3 |
4 | message Txs {
5 | repeated bytes txs = 1;
6 | }
7 |
8 | message Message {
9 | oneof sum {
10 | Txs txs = 1;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/spec/consensus/light-client/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | parent:
4 | title: Light Client
5 | order: false
6 | ---
7 | # Tendermint Light Client Protocol
8 |
9 | Deprecated, please see [light-client](../../light-client/README.md).
10 |
--------------------------------------------------------------------------------
/buf.yaml:
--------------------------------------------------------------------------------
1 | version: v1beta1
2 |
3 | build:
4 | roots:
5 | - proto
6 | - third_party/proto
7 | lint:
8 | use:
9 | - BASIC
10 | - FILE_LOWER_SNAKE_CASE
11 | - UNARY_RPC
12 | ignore:
13 | - gogoproto
14 | breaking:
15 | use:
16 | - FILE
17 |
--------------------------------------------------------------------------------
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | Language: Proto
3 | BasedOnStyle: Google
4 | IndentWidth: 2
5 | ColumnLimit: 0
6 | AlignConsecutiveAssignments: true
7 | AlignConsecutiveDeclarations: true
8 | SpacesInSquareBrackets: true
9 | ReflowComments: true
10 | SortIncludes: true
11 | SortUsingDeclarations: true
12 |
--------------------------------------------------------------------------------
/spec/light-client/detection/005bmc-apalache-error.csv:
--------------------------------------------------------------------------------
1 | no;filename;tool;timeout;init;inv;next;args
2 | 1;LCD_MC3_3_faulty.tla;apalache;1h;;PrecisionInvGrayZone;;--length=10
3 | 2;LCD_MC3_4_faulty.tla;apalache;1h;;PrecisionInvGrayZone;;--length=10
4 | 3;LCD_MC4_4_faulty.tla;apalache;1h;;PrecisionInvGrayZone;;--length=10
5 |
--------------------------------------------------------------------------------
/spec/light-client/verification/005bmc-apalache-error.csv:
--------------------------------------------------------------------------------
1 | no;filename;tool;timeout;init;inv;next;args
2 | 1;LCD_MC3_3_faulty.tla;apalache;1h;;PrecisionInvGrayZone;;--length=10
3 | 2;LCD_MC3_4_faulty.tla;apalache;1h;;PrecisionInvGrayZone;;--length=10
4 | 3;LCD_MC4_4_faulty.tla;apalache;1h;;PrecisionInvGrayZone;;--length=10
5 |
--------------------------------------------------------------------------------
/spec/light-client/accountability/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 | # The script to run all experiments at once
4 |
5 | export SCRIPTS_DIR=~/devl/apalache-tests/scripts
6 | export BUILDS="unstable"
7 | export BENCHMARK=001indinv-apalache
8 | export RUN_SCRIPT=./run-all.sh # alternatively, use ./run-parallel.sh
9 | make -e -f ~/devl/apalache-tests/Makefile.common
10 |
--------------------------------------------------------------------------------
/spec/blockchain/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | parent:
4 | title: Blockchain
5 | order: false
6 | ---
7 |
8 | # Blockchain
9 |
10 | This section describes the core types and functionality of the Tendermint protocol implementation.
11 |
12 | [Core Data Structures](../core/data_structures.md)
13 | [Encoding](../core/encoding.md)
14 | [State](../core/state.md)
15 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to the spec will be documented in this file for easy reference. Changes are grouped by version.
4 |
5 | ## [Unreleased]
6 |
7 | - [RPC] [#276](https://github.com/tendermint/spec/pull/276): Add specification for RPC (@marbar3778)
8 | - [RPC] [#304](https://github.com/tendermint/spec/pull/304): Clarify timestamp format (@marbar3778)
9 |
--------------------------------------------------------------------------------
/.github/workflows/action.yml:
--------------------------------------------------------------------------------
1 | name: Check Markdown links
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | branches: [master]
9 |
10 | jobs:
11 | markdown-link-check:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@master
15 | - uses: gaurav-nelson/github-action-markdown-link-check@1.0.13
16 | with:
17 | check-modified-files-only: 'yes'
18 |
--------------------------------------------------------------------------------
/proto/tendermint/crypto/keys.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package tendermint.crypto;
3 |
4 | import "gogoproto/gogo.proto";
5 |
6 | // PublicKey defines the keys available for use with Tendermint Validators
7 | message PublicKey {
8 | option (gogoproto.compare) = true;
9 | option (gogoproto.equal) = true;
10 |
11 | oneof sum {
12 | bytes ed25519 = 1;
13 | bytes secp256k1 = 2;
14 | bytes sr25519 = 3;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/proto/tendermint/version/types.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package tendermint.version;
3 |
4 | import "gogoproto/gogo.proto";
5 |
6 | // Consensus captures the consensus rules for processing a block in the
7 | // blockchain, including all blockchain data structures and the rules of the
8 | // application's state transition machine.
9 | message Consensus {
10 | option (gogoproto.equal) = true;
11 |
12 | uint64 block = 1;
13 | uint64 app = 2;
14 | }
15 |
--------------------------------------------------------------------------------
/proto/tendermint/types/block.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package tendermint.types;
3 |
4 | import "gogoproto/gogo.proto";
5 | import "tendermint/types/types.proto";
6 | import "tendermint/types/evidence.proto";
7 |
8 | message Block {
9 | Header header = 1 [(gogoproto.nullable) = false];
10 | Data data = 2 [(gogoproto.nullable) = false];
11 | tendermint.types.EvidenceList evidence = 3 [(gogoproto.nullable) = false];
12 | Commit last_commit = 4;
13 | }
14 |
--------------------------------------------------------------------------------
/spec/core/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | parent:
4 | title: Core
5 | order: 3
6 | ---
7 |
8 | **THIS REPOSITORY HAS BEEN ARCHIVED. THE TENDERMINT SPECIFICATION IS NOW LOCATED IN THE [TENDERMINT/TENDERMINT](https://github.com/tendermint/tendermint/tree/master/spec) REPOSITORY.**
9 |
10 | ---
11 |
12 | This section describes the core types and functionality of the Tendermint protocol implementation.
13 |
14 | - [Core Data Structures](./data_structures.md)
15 | - [Encoding](./encoding.md)
16 | - [Genesis](./genesis.md)
17 | - [State](./state.md)
18 |
--------------------------------------------------------------------------------
/proto/tendermint/p2p/pex.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package tendermint.p2p;
3 |
4 | import "gogoproto/gogo.proto";
5 |
6 | message PexAddress {
7 | string url = 1 [(gogoproto.customname) = "URL"];
8 |
9 | reserved 2, 3; // See https://github.com/tendermint/spec/pull/352
10 | }
11 |
12 | message PexRequest {}
13 |
14 | message PexResponse {
15 | repeated PexAddress addresses = 1 [(gogoproto.nullable) = false];
16 | }
17 |
18 | message PexMessage {
19 | reserved 1, 2; // See https://github.com/tendermint/spec/pull/352
20 | oneof sum {
21 | PexRequest pex_request = 3;
22 | PexResponse pex_response = 4;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.github/workflows/stale.yml:
--------------------------------------------------------------------------------
1 | name: "Close stale pull requests"
2 | on:
3 | schedule:
4 | - cron: "0 0 * * *"
5 |
6 | jobs:
7 | stale:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/stale@v4
11 | with:
12 | repo-token: ${{ secrets.GITHUB_TOKEN }}
13 | stale-pr-message: "This pull request has been automatically marked as stale because it has not had
14 | recent activity. It will be closed if no further activity occurs. Thank you
15 | for your contributions."
16 | days-before-stale: -1
17 | days-before-pr-stale: 14
18 | days-before-pr-close: 4
19 | exempt-pr-labels: "pinned, proposal"
20 |
--------------------------------------------------------------------------------
/buf.gen.yaml:
--------------------------------------------------------------------------------
1 | # The version of the generation template (required).
2 | # The only currently-valid value is v1beta1.
3 | version: v1beta1
4 |
5 | # The plugins to run.
6 | plugins:
7 | # The name of the plugin.
8 | - name: gogofaster
9 | # The directory where the generated proto output will be written.
10 | # The directory is relative to where the generation tool was run.
11 | out: proto
12 | # Set options to assign import paths to the well-known types
13 | # and to enable service generation.
14 | opt: Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/duration.proto=github.com/golang/protobuf/ptypes/duration,plugins=grpc,paths=source_relative
15 |
--------------------------------------------------------------------------------
/spec/light-client/detection/004bmc-apalache-ok.csv:
--------------------------------------------------------------------------------
1 | no;filename;tool;timeout;init;inv;next;args
2 | 1;LCD_MC3_3_faulty.tla;apalache;1h;;CommonHeightOnEvidenceInv;;--length=10
3 | 2;LCD_MC3_3_faulty.tla;apalache;1h;;AccuracyInv;;--length=10
4 | 3;LCD_MC3_3_faulty.tla;apalache;1h;;PrecisionInvLocal;;--length=10
5 | 4;LCD_MC3_4_faulty.tla;apalache;1h;;CommonHeightOnEvidenceInv;;--length=10
6 | 5;LCD_MC3_4_faulty.tla;apalache;1h;;AccuracyInv;;--length=10
7 | 6;LCD_MC3_4_faulty.tla;apalache;1h;;PrecisionInvLocal;;--length=10
8 | 7;LCD_MC4_4_faulty.tla;apalache;1h;;CommonHeightOnEvidenceInv;;--length=10
9 | 8;LCD_MC4_4_faulty.tla;apalache;1h;;AccuracyInv;;--length=10
10 | 9;LCD_MC4_4_faulty.tla;apalache;1h;;PrecisionInvLocal;;--length=10
11 |
--------------------------------------------------------------------------------
/spec/light-client/verification/004bmc-apalache-ok.csv:
--------------------------------------------------------------------------------
1 | no;filename;tool;timeout;init;inv;next;args
2 | 1;LCD_MC3_3_faulty.tla;apalache;1h;;CommonHeightOnEvidenceInv;;--length=10
3 | 2;LCD_MC3_3_faulty.tla;apalache;1h;;AccuracyInv;;--length=10
4 | 3;LCD_MC3_3_faulty.tla;apalache;1h;;PrecisionInvLocal;;--length=10
5 | 4;LCD_MC3_4_faulty.tla;apalache;1h;;CommonHeightOnEvidenceInv;;--length=10
6 | 5;LCD_MC3_4_faulty.tla;apalache;1h;;AccuracyInv;;--length=10
7 | 6;LCD_MC3_4_faulty.tla;apalache;1h;;PrecisionInvLocal;;--length=10
8 | 7;LCD_MC4_4_faulty.tla;apalache;1h;;CommonHeightOnEvidenceInv;;--length=10
9 | 8;LCD_MC4_4_faulty.tla;apalache;1h;;AccuracyInv;;--length=10
10 | 9;LCD_MC4_4_faulty.tla;apalache;1h;;PrecisionInvLocal;;--length=10
11 |
--------------------------------------------------------------------------------
/proto/tendermint/p2p/conn.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package tendermint.p2p;
3 |
4 | import "gogoproto/gogo.proto";
5 | import "tendermint/crypto/keys.proto";
6 |
7 | message PacketPing {}
8 |
9 | message PacketPong {}
10 |
11 | message PacketMsg {
12 | int32 channel_id = 1 [(gogoproto.customname) = "ChannelID"];
13 | bool eof = 2 [(gogoproto.customname) = "EOF"];
14 | bytes data = 3;
15 | }
16 |
17 | message Packet {
18 | oneof sum {
19 | PacketPing packet_ping = 1;
20 | PacketPong packet_pong = 2;
21 | PacketMsg packet_msg = 3;
22 | }
23 | }
24 |
25 | message AuthSigMessage {
26 | tendermint.crypto.PublicKey pub_key = 1 [(gogoproto.nullable) = false];
27 | bytes sig = 2;
28 | }
29 |
--------------------------------------------------------------------------------
/.github/workflows/proto-check.yml:
--------------------------------------------------------------------------------
1 | name: Proto Check
2 | # Protobuf runs buf (https://buf.build/) lint and check-breakage
3 | # This workflow is only run when a file in the proto directory
4 | # has been modified.
5 | on:
6 | workflow_dispatch: # allow running workflow manually
7 | pull_request:
8 | paths:
9 | - "proto/*"
10 | jobs:
11 | proto-lint:
12 | runs-on: ubuntu-latest
13 | timeout-minutes: 4
14 | steps:
15 | - uses: actions/checkout@v2.4.0
16 | - name: lint
17 | run: make proto-lint
18 | proto-breakage:
19 | runs-on: ubuntu-latest
20 | timeout-minutes: 4
21 | steps:
22 | - uses: actions/checkout@v2.4.0
23 | - name: check-breakage
24 | run: make proto-check-breaking-ci
25 |
--------------------------------------------------------------------------------
/ivy-proofs/count_lines.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | r='^\s*$\|^\s*\#\|^\s*\}\s*$\|^\s*{\s*$' # removes comments and blank lines and lines that contain only { or }
4 | N1=`cat tendermint.ivy domain_model.ivy network_shim.ivy | grep -v $r'\|.*invariant.*' | wc -l`
5 | N2=`cat abstract_tendermint.ivy | grep "observed_" | wc -l` # the observed_* variables specify the observations of the nodes
6 | SPEC_LINES=`expr $N1 + $N2`
7 | echo "spec lines: $SPEC_LINES"
8 | N3=`cat abstract_tendermint.ivy | grep -v $r'\|.*observed_.*' | wc -l`
9 | N4=`cat accountable_safety_1.ivy | grep -v $r | wc -l`
10 | PROOF_LINES=`expr $N3 + $N4`
11 | echo "proof lines: $PROOF_LINES"
12 | RATIO=`bc <<< "scale=2;$PROOF_LINES / $SPEC_LINES"`
13 | echo "proof-to-code ratio for the accountable-safety property: $RATIO"
14 |
--------------------------------------------------------------------------------
/spec/consensus/consensus-paper/README.md:
--------------------------------------------------------------------------------
1 | # Tendermint-spec
2 |
3 | The repository contains the specification (and the proofs) of the Tendermint
4 | consensus protocol.
5 |
6 | ## How to install Latex on Mac OS
7 |
8 | MacTex is Latex distribution for Mac OS. You can download it [here](http://www.tug.org/mactex/mactex-download.html).
9 |
10 | Popular IDE for Latex-based projects is TexStudio. It can be downloaded
11 | [here](https://www.texstudio.org/).
12 |
13 | ## How to build project
14 |
15 | In order to compile the latex files (and write bibliography), execute
16 |
17 | `$ pdflatex paper`
18 | `$ bibtex paper`
19 | `$ pdflatex paper`
20 | `$ pdflatex paper`
21 |
22 | The generated file is paper.pdf. You can open it with
23 |
24 | `$ open paper.pdf`
25 |
--------------------------------------------------------------------------------
/proto/tendermint/types/validator.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package tendermint.types;
3 |
4 | import "gogoproto/gogo.proto";
5 | import "tendermint/crypto/keys.proto";
6 |
7 | message ValidatorSet {
8 | repeated Validator validators = 1;
9 | Validator proposer = 2;
10 | int64 total_voting_power = 3;
11 | }
12 |
13 | message Validator {
14 | bytes address = 1;
15 | tendermint.crypto.PublicKey pub_key = 2 [(gogoproto.nullable) = false];
16 | int64 voting_power = 3;
17 | int64 proposer_priority = 4;
18 | }
19 |
20 | message SimpleValidator {
21 | tendermint.crypto.PublicKey pub_key = 1;
22 | int64 voting_power = 2;
23 | }
24 |
--------------------------------------------------------------------------------
/spec/light-client/attacks/MC_5_3.tla:
--------------------------------------------------------------------------------
1 | ------------------------- MODULE MC_5_3 -------------------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4", "n5"}
4 | COMMON_HEIGHT == 1
5 | CONFLICT_HEIGHT == 3
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | FAULTY_RATIO == <<1, 2>> \* < 1 / 2 faulty validators
8 |
9 | VARIABLES
10 | blockchain, \* the reference blockchain
11 | refClock, \* current time in the reference blockchain
12 | Faulty, \* the set of faulty validators
13 | state, \* the state of the light client detector
14 | conflictingBlock, \* an evidence that two peers reported conflicting blocks
15 | attackers
16 |
17 | INSTANCE Isolation_001_draft
18 | ============================================================================
19 |
--------------------------------------------------------------------------------
/spec/p2p/messages/evidence.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 3
3 | ---
4 |
5 | # Evidence
6 |
7 | ## Channel
8 |
9 | Evidence has one channel. The channel identifier is listed below.
10 |
11 | | Name | Number |
12 | |-----------------|--------|
13 | | EvidenceChannel | 56 |
14 |
15 | ## Message Types
16 |
17 | ### Evidence
18 |
19 | Verified evidence that has already been propagated throughout the network. This evidence will appear within the EvidenceList struct of a [block](../../core/data_structures.md#block) as well.
20 |
21 | | Name | Type | Description | Field Number |
22 | |----------|-------------------------------------------------------------|------------------------|--------------|
23 | | evidence | [Evidence](../../core/data_structures.md#evidence) | Valid evidence | 1 |
24 |
--------------------------------------------------------------------------------
/spec/light-client/accountability/results/001indinv-apalache-unstable.csv:
--------------------------------------------------------------------------------
1 | 01:no,02:tool,03:status,04:time_sec,05:depth,05:mem_kb,10:ninit_trans,11:ninit_trans,12:ncells,13:nclauses,14:navg_clause_len
2 | 1,apalache,NoError,704,1,3215424,0,0,217385,1305718,89
3 | 2,apalache,NoError,699,1,3195020,0,0,207969,1341979,88
4 | 3,apalache,NoError,1018,1,4277060,0,0,311798,2028544,101
5 | 4,apalache,NoError,889,1,4080012,0,0,290989,1951616,103
6 | 5,apalache,NoError,9,0,577100,0,0,2045,14655,42
7 | 6,apalache,NoError,10,0,673772,0,0,2913,28213,43
8 | 7,apalache,NoError,8,0,651008,0,0,2214,17077,44
9 | 8,apalache,NoError,10,0,683188,0,0,3082,32651,45
10 | 9,apalache,NoError,340,0,3053848,0,0,196943,889859,108
11 | 10,apalache,NoError,517,0,6424536,0,0,2856378,3802779,34
12 | 11,apalache,NoError,587,0,4028516,0,0,284369,1343296,128
13 | 12,apalache,NoError,880,0,7881148,0,0,4382556,5778072,38
14 |
--------------------------------------------------------------------------------
/spec/light-client/accountability/typedefs.tla:
--------------------------------------------------------------------------------
1 | -------------------- MODULE typedefs ---------------------------
2 | (*
3 | @typeAlias: PROCESS = Str;
4 | @typeAlias: VALUE = Str;
5 | @typeAlias: STEP = Str;
6 | @typeAlias: ROUND = Int;
7 | @typeAlias: ACTION = Str;
8 | @typeAlias: TRACE = Seq(Str);
9 | @typeAlias: PROPMESSAGE =
10 | [
11 | type: STEP,
12 | src: PROCESS,
13 | round: ROUND,
14 | proposal: VALUE,
15 | validRound: ROUND
16 | ];
17 | @typeAlias: PREMESSAGE =
18 | [
19 | type: STEP,
20 | src: PROCESS,
21 | round: ROUND,
22 | id: VALUE
23 | ];
24 | @typeAlias: MESSAGE =
25 | [
26 | type: STEP,
27 | src: PROCESS,
28 | round: ROUND,
29 | proposal: VALUE,
30 | validRound: ROUND,
31 | id: VALUE
32 | ];
33 | *)
34 | TypeAliases == TRUE
35 |
36 | =============================================================================
--------------------------------------------------------------------------------
/spec/p2p/messages/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | parent:
4 | title: Messages
5 | order: 1
6 | ---
7 |
8 | # Messages
9 |
10 | An implementation of the spec consists of many components. While many parts of these components are implementation specific, the p2p messages are not. In this section we will be covering all the p2p messages of components.
11 |
12 | There are two parts to the P2P messages, the message and the channel. The channel is message specific and messages are specific to components of Tendermint. When a node connect to a peer it will tell the other node which channels are available. This notifies the peer what services the connecting node offers. You can read more on channels in [connection.md](../connection.md#mconnection)
13 |
14 | - [Block Sync](./block-sync.md)
15 | - [Mempool](./mempool.md)
16 | - [Evidence](./evidence.md)
17 | - [State Sync](./state-sync.md)
18 | - [Pex](./pex.md)
19 | - [Consensus](./consensus.md)
20 |
--------------------------------------------------------------------------------
/.github/workflows/linter.yml:
--------------------------------------------------------------------------------
1 | name: Lint
2 | on:
3 | push:
4 | branches:
5 | - master
6 | pull_request:
7 | branches: [master]
8 |
9 | jobs:
10 | build:
11 | name: Super linter
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Checkout Code
15 | uses: actions/checkout@v2
16 | with:
17 | # Full git history is needed to get a proper list of changed files within `super-linter`
18 | fetch-depth: 0
19 | - name: Lint Code Base
20 | uses: docker://github/super-linter:v4
21 | env:
22 | LINTER_RULES_PATH: .
23 | VALIDATE_ALL_CODEBASE: false
24 | DEFAULT_BRANCH: master
25 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26 | VALIDATE_MD: true
27 | MARKDOWN_CONFIG_FILE: .markdownlint.yml
28 | VALIDATE_PROTOBUF: false
29 | VALIDATE_JSCPD: false
30 | VALIDATE_NATURAL_LANGUAGE: false
31 |
--------------------------------------------------------------------------------
/spec/light-client/verification/MC5_5_faulty.tla:
--------------------------------------------------------------------------------
1 | ----------------- MODULE MC5_5_faulty ---------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4", "n5"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 5
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == FALSE
10 | FAULTY_RATIO == <<2, 3>> \* < 1 / 3 faulty validators
11 |
12 | VARIABLES
13 | state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified,
14 | nprobes,
15 | localClock,
16 | refClock, blockchain, Faulty
17 |
18 | (* the light client previous state components, used for monitoring *)
19 | VARIABLES
20 | prevVerified,
21 | prevCurrent,
22 | prevLocalClock,
23 | prevVerdict
24 |
25 | INSTANCE Lightclient_003_draft
26 | ============================================================================
27 |
--------------------------------------------------------------------------------
/spec/light-client/verification/MC4_4_correct.tla:
--------------------------------------------------------------------------------
1 | ------------------------- MODULE MC4_4_correct ---------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 4
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == TRUE
10 | FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators
11 |
12 | VARIABLES
13 | state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified,
14 | nprobes,
15 | localClock,
16 | refClock, blockchain, Faulty
17 |
18 | (* the light client previous state components, used for monitoring *)
19 | VARIABLES
20 | prevVerified,
21 | prevCurrent,
22 | prevLocalClock,
23 | prevVerdict
24 |
25 | INSTANCE Lightclient_003_draft
26 | ============================================================================
27 |
--------------------------------------------------------------------------------
/spec/light-client/verification/MC4_5_correct.tla:
--------------------------------------------------------------------------------
1 | ------------------------- MODULE MC4_5_correct ---------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 5
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == TRUE
10 | FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators
11 |
12 | VARIABLES
13 | state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified,
14 | nprobes,
15 | localClock,
16 | refClock, blockchain, Faulty
17 |
18 | (* the light client previous state components, used for monitoring *)
19 | VARIABLES
20 | prevVerified,
21 | prevCurrent,
22 | prevLocalClock,
23 | prevVerdict
24 |
25 | INSTANCE Lightclient_003_draft
26 | ============================================================================
27 |
--------------------------------------------------------------------------------
/spec/light-client/verification/MC4_5_faulty.tla:
--------------------------------------------------------------------------------
1 | ------------------------- MODULE MC4_5_faulty ---------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 5
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | IS_PRICLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | MARY_CORRECT == FALSE
10 | FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators
11 |
12 | VARIABLES
13 | state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified,
14 | nprobes,
15 | localClock,
16 | refClock, blockchain, Faulty
17 |
18 | (* the light client previous state components, used for monitoring *)
19 | VARIABLES
20 | prevVerified,
21 | prevCurrent,
22 | prevLocalClock,
23 | prevVerdict
24 |
25 | INSTANCE Lightclient_003_draft
26 | ============================================================================
27 |
--------------------------------------------------------------------------------
/spec/light-client/verification/MC4_6_faulty.tla:
--------------------------------------------------------------------------------
1 | ------------------------- MODULE MC4_6_faulty ---------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 6
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | IS_PRCLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | IMARY_CORRECT == FALSE
10 | FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators
11 |
12 | VARIABLES
13 | state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified,
14 | nprobes,
15 | localClock,
16 | refClock, blockchain, Faulty
17 |
18 | (* the light client previous state components, used for monitoring *)
19 | VARIABLES
20 | prevVerified,
21 | prevCurrent,
22 | prevLocalClock,
23 | prevVerdict
24 |
25 | INSTANCE Lightclient_003_draft
26 | ============================================================================
27 |
--------------------------------------------------------------------------------
/spec/light-client/verification/MC4_7_faulty.tla:
--------------------------------------------------------------------------------
1 | ------------------------- MODULE MC4_7_faulty ---------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 7
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == FALSE
10 | FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators
11 |
12 | VARIABLES
13 | state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified,
14 | nprobes,
15 | localClock,
16 | refClock, blockchain, Faulty
17 |
18 | (* the light client previous state components, used for monitoring *)
19 | VARIABLES
20 | prevVerified,
21 | prevCurrent,
22 | prevLocalClock,
23 | prevVerdict
24 |
25 | INSTANCE Lightclient_003_draft
26 | ============================================================================
27 |
--------------------------------------------------------------------------------
/spec/light-client/verification/MC4_3_correct.tla:
--------------------------------------------------------------------------------
1 | ---------------------------- MODULE MC4_3_correct ---------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 3
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == TRUE
10 | FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators
11 |
12 | VARIABLES
13 | state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified,
14 | nprobes,
15 | localClock,
16 | refClock, blockchain, Faulty
17 |
18 | (* the light client previous state components, used for monitoring *)
19 | VARIABLES
20 | prevVerified,
21 | prevCurrent,
22 | prevLocalClock,
23 | prevVerdict
24 |
25 | INSTANCE Lightclient_003_draft
26 | ==============================================================================
27 |
--------------------------------------------------------------------------------
/spec/light-client/verification/MC4_3_faulty.tla:
--------------------------------------------------------------------------------
1 | ---------------------------- MODULE MC4_3_faulty ---------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 3
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == FALSE
10 | FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators
11 |
12 | VARIABLES
13 | state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified,
14 | nprobes,
15 | localClock,
16 | refClock, blockchain, Faulty
17 |
18 | (* the light client previous state components, used for monitoring *)
19 | VARIABLES
20 | prevVerified,
21 | prevCurrent,
22 | prevLocalClock,
23 | prevVerdict
24 |
25 | INSTANCE Lightclient_003_draft
26 | ==============================================================================
27 |
--------------------------------------------------------------------------------
/spec/light-client/verification/MC4_4_faulty.tla:
--------------------------------------------------------------------------------
1 | ---------------------------- MODULE MC4_4_faulty ---------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 4
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == FALSE
10 | FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators
11 |
12 | VARIABLES
13 | state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified,
14 | nprobes,
15 | localClock,
16 | refClock, blockchain, Faulty
17 |
18 | (* the light client previous state components, used for monitoring *)
19 | VARIABLES
20 | prevVerified,
21 | prevCurrent,
22 | prevLocalClock,
23 | prevVerdict
24 |
25 | INSTANCE Lightclient_003_draft
26 | ==============================================================================
27 |
--------------------------------------------------------------------------------
/spec/light-client/verification/MC5_7_faulty.tla:
--------------------------------------------------------------------------------
1 | ------------------------- MODULE MC5_7_faulty ---------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4", "n5"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 7
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == FALSE
10 | FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators
11 |
12 | VARIABLES
13 | state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified,
14 | nprobes,
15 | localClock,
16 | refClock, blockchain, Faulty
17 |
18 | (* the light client previous state components, used for monitoring *)
19 | VARIABLES
20 | prevVerified,
21 | prevCurrent,
22 | prevLocalClock,
23 | prevVerdict
24 |
25 | INSTANCE Lightclient_003_draft
26 | ============================================================================
27 |
--------------------------------------------------------------------------------
/spec/light-client/verification/MC5_5_correct.tla:
--------------------------------------------------------------------------------
1 | ------------------------- MODULE MC5_5_correct ---------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4", "n5"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 5
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == TRUE
10 | FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators
11 |
12 | VARIABLES
13 | state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified,
14 | nprobes,
15 | localClock,
16 | refClock, blockchain, Faulty
17 |
18 | (* the light client previous state components, used for monitoring *)
19 | VARIABLES
20 | prevVerified,
21 | prevCurrent,
22 | prevLocalClock,
23 | prevVerdict
24 |
25 | INSTANCE Lightclient_003_draft
26 | ============================================================================
27 |
--------------------------------------------------------------------------------
/spec/light-client/verification/MC4_4_correct_drifted.tla:
--------------------------------------------------------------------------------
1 | ---------------------- MODULE MC4_4_correct_drifted ---------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 4
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 30 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == TRUE
10 | FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators
11 |
12 | VARIABLES
13 | state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified,
14 | nprobes,
15 | localClock,
16 | refClock, blockchain, Faulty
17 |
18 | (* the light client previous state components, used for monitoring *)
19 | VARIABLES
20 | prevVerified,
21 | prevCurrent,
22 | prevLocalClock,
23 | prevVerdict
24 |
25 | INSTANCE Lightclient_003_draft
26 | ==============================================================================
27 |
--------------------------------------------------------------------------------
/spec/light-client/verification/MC4_4_faulty_drifted.tla:
--------------------------------------------------------------------------------
1 | ---------------------- MODULE MC4_4_faulty_drifted ---------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 4
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 30 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == FALSE
10 | FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators
11 |
12 | VARIABLES
13 | state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified,
14 | nprobes,
15 | localClock,
16 | refClock, blockchain, Faulty
17 |
18 | (* the light client previous state components, used for monitoring *)
19 | VARIABLES
20 | prevVerified,
21 | prevCurrent,
22 | prevLocalClock,
23 | prevVerdict
24 |
25 | INSTANCE Lightclient_003_draft
26 | ==============================================================================
27 |
--------------------------------------------------------------------------------
/spec/light-client/verification/MC7_5_faulty.tla:
--------------------------------------------------------------------------------
1 | ------------------------- MODULE MC7_5_faulty ---------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4", "n5", "n6", "n7"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 5
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == FALSE
10 | FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators
11 |
12 | VARIABLES
13 | state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified,
14 | nprobes,
15 | localClock,
16 | refClock, blockchain, Faulty
17 |
18 | (* the light client previous state components, used for monitoring *)
19 | VARIABLES
20 | prevVerified,
21 | prevCurrent,
22 | prevLocalClock,
23 | prevVerdict
24 |
25 | INSTANCE Lightclient_003_draft
26 | ============================================================================
27 |
--------------------------------------------------------------------------------
/spec/light-client/verification/MC7_7_faulty.tla:
--------------------------------------------------------------------------------
1 | ------------------------- MODULE MC7_7_faulty ---------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4", "n5", "n6", "n7"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 7
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == FALSE
10 | FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators
11 |
12 | VARIABLES
13 | state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified,
14 | nprobes,
15 | localClock,
16 | refClock, blockchain, Faulty
17 |
18 | (* the light client previous state components, used for monitoring *)
19 | VARIABLES
20 | prevVerified,
21 | prevCurrent,
22 | prevLocalClock,
23 | prevVerdict
24 |
25 | INSTANCE Lightclient_003_draft
26 | ============================================================================
27 |
--------------------------------------------------------------------------------
/proto/tendermint/crypto/proof.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package tendermint.crypto;
3 |
4 | import "gogoproto/gogo.proto";
5 |
6 | message Proof {
7 | int64 total = 1;
8 | int64 index = 2;
9 | bytes leaf_hash = 3;
10 | repeated bytes aunts = 4;
11 | }
12 |
13 | message ValueOp {
14 | // Encoded in ProofOp.Key.
15 | bytes key = 1;
16 |
17 | // To encode in ProofOp.Data
18 | Proof proof = 2;
19 | }
20 |
21 | message DominoOp {
22 | string key = 1;
23 | string input = 2;
24 | string output = 3;
25 | }
26 |
27 | // ProofOp defines an operation used for calculating Merkle root
28 | // The data could be arbitrary format, providing nessecary data
29 | // for example neighbouring node hash
30 | message ProofOp {
31 | string type = 1;
32 | bytes key = 2;
33 | bytes data = 3;
34 | }
35 |
36 | // ProofOps is Merkle proof defined by the list of ProofOps
37 | message ProofOps {
38 | repeated ProofOp ops = 1 [(gogoproto.nullable) = false];
39 | }
40 |
--------------------------------------------------------------------------------
/proto/Dockerfile:
--------------------------------------------------------------------------------
1 | # This Dockerfile defines an image containing tools for linting, formatting,
2 | # and compiling the Tendermint protos.
3 | FROM golang:1.17-alpine
4 |
5 | # Install a commonly used set of programs for use with our protos.
6 | # clang-extra-tools is included here because it provides clang-format,
7 | # used to format the .proto files.
8 | RUN apk add --no-cache build-base clang-extra-tools curl git
9 |
10 | ENV GOLANG_PROTOBUF_VERSION=1.3.1 \
11 | GOGO_PROTOBUF_VERSION=1.3.2
12 |
13 | # Retrieve the go protoc programs and copy them into the PATH
14 | RUN go install github.com/golang/protobuf/protoc-gen-go@v${GOLANG_PROTOBUF_VERSION} && \
15 | go install github.com/gogo/protobuf/protoc-gen-gogo@v${GOGO_PROTOBUF_VERSION} && \
16 | go install github.com/gogo/protobuf/protoc-gen-gogofaster@v${GOGO_PROTOBUF_VERSION} && \
17 | mv "$(go env GOPATH)"/bin/* /usr/local/bin/
18 |
19 | # Copy the 'buf' program out of the buildbuf/buf container.
20 | COPY --from=bufbuild/buf:latest /usr/local/bin/* /usr/local/bin/
21 |
--------------------------------------------------------------------------------
/spec/light-client/verification/MC5_5_faulty_peer_two_thirds_faulty.tla:
--------------------------------------------------------------------------------
1 | ----------------- MODULE MC5_5_faulty_peer_two_thirds_faulty ---------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4", "n5"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 5
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == FALSE
10 | FAULTY_RATIO == <<2, 3>> \* < 2 / 3 faulty validators
11 |
12 | VARIABLES
13 | state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified,
14 | nprobes,
15 | localClock,
16 | refClock, blockchain, Faulty
17 |
18 | (* the light client previous state components, used for monitoring *)
19 | VARIABLES
20 | prevVerified,
21 | prevCurrent,
22 | prevLocalClock,
23 | prevVerdict
24 |
25 | INSTANCE Lightclient_003_draft
26 | ============================================================================
27 |
--------------------------------------------------------------------------------
/spec/light-client/verification/MC5_5_correct_peer_two_thirds_faulty.tla:
--------------------------------------------------------------------------------
1 | ------------------- MODULE MC5_5_correct_peer_two_thirds_faulty ----------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4", "n5"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 5
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == TRUE
10 | FAULTY_RATIO == <<2, 3>> \* < 1 / 3 faulty validators
11 |
12 | VARIABLES
13 | state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified,
14 | nprobes,
15 | localClock,
16 | refClock, blockchain, Faulty
17 |
18 | (* the light client previous state components, used for monitoring *)
19 | VARIABLES
20 | prevVerified,
21 | prevCurrent,
22 | prevLocalClock,
23 | prevVerdict
24 |
25 | INSTANCE Lightclient_003_draft
26 | ============================================================================
27 |
--------------------------------------------------------------------------------
/spec/light-client/accountability/001indinv-apalache.csv:
--------------------------------------------------------------------------------
1 | no,filename,tool,timeout,init,inv,next,args
2 | 1,MC_n4_f1.tla,apalache,10h,TypedInv,TypedInv,,--length=1 --cinit=ConstInit
3 | 2,MC_n4_f2.tla,apalache,10h,TypedInv,TypedInv,,--length=1 --cinit=ConstInit
4 | 3,MC_n5_f1.tla,apalache,10h,TypedInv,TypedInv,,--length=1 --cinit=ConstInit
5 | 4,MC_n5_f2.tla,apalache,10h,TypedInv,TypedInv,,--length=1 --cinit=ConstInit
6 | 5,MC_n4_f1.tla,apalache,20h,Init,TypedInv,,--length=0 --cinit=ConstInit
7 | 6,MC_n4_f2.tla,apalache,20h,Init,TypedInv,,--length=0 --cinit=ConstInit
8 | 7,MC_n5_f1.tla,apalache,20h,Init,TypedInv,,--length=0 --cinit=ConstInit
9 | 8,MC_n5_f2.tla,apalache,20h,Init,TypedInv,,--length=0 --cinit=ConstInit
10 | 9,MC_n4_f1.tla,apalache,20h,TypedInv,Agreement,,--length=0 --cinit=ConstInit
11 | 10,MC_n4_f2.tla,apalache,20h,TypedInv,Accountability,,--length=0 --cinit=ConstInit
12 | 11,MC_n5_f1.tla,apalache,20h,TypedInv,Agreement,,--length=0 --cinit=ConstInit
13 | 12,MC_n5_f2.tla,apalache,20h,TypedInv,Accountability,,--length=0 --cinit=ConstInit
14 |
--------------------------------------------------------------------------------
/ivy-proofs/check_proofs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # returns non-zero error code if any proof fails
4 |
5 | success=0
6 | log_dir=$(cat /dev/urandom | tr -cd 'a-f0-9' | head -c 6)
7 | cmd="ivy_check seed=$RANDOM"
8 | mkdir -p output/$log_dir
9 |
10 | echo "Checking classic safety:"
11 | res=$($cmd classic_safety.ivy | tee "output/$log_dir/classic_safety.txt" | tail -n 1)
12 | if [ "$res" = "OK" ]; then
13 | echo "OK"
14 | else
15 | echo "FAILED"
16 | success=1
17 | fi
18 |
19 | echo "Checking accountable safety 1:"
20 | res=$($cmd accountable_safety_1.ivy | tee "output/$log_dir/accountable_safety_1.txt" | tail -n 1)
21 | if [ "$res" = "OK" ]; then
22 | echo "OK"
23 | else
24 | echo "FAILED"
25 | success=1
26 | fi
27 |
28 | echo "Checking accountable safety 2:"
29 | res=$($cmd complete=fo accountable_safety_2.ivy | tee "output/$log_dir/accountable_safety_2.txt" | tail -n 1)
30 | if [ "$res" = "OK" ]; then
31 | echo "OK"
32 | else
33 | echo "FAILED"
34 | success=1
35 | fi
36 |
37 | echo
38 | echo "See ivy_check output in the output/ folder"
39 | exit $success
40 |
--------------------------------------------------------------------------------
/proto/tendermint/blocksync/types.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package tendermint.blocksync;
3 |
4 | import "tendermint/types/block.proto";
5 |
6 | // BlockRequest requests a block for a specific height
7 | message BlockRequest {
8 | int64 height = 1;
9 | }
10 |
11 | // NoBlockResponse informs the node that the peer does not have block at the
12 | // requested height
13 | message NoBlockResponse {
14 | int64 height = 1;
15 | }
16 |
17 | // BlockResponse returns block to the requested
18 | message BlockResponse {
19 | tendermint.types.Block block = 1;
20 | }
21 |
22 | // StatusRequest requests the status of a peer.
23 | message StatusRequest {}
24 |
25 | // StatusResponse is a peer response to inform their status.
26 | message StatusResponse {
27 | int64 height = 1;
28 | int64 base = 2;
29 | }
30 |
31 | message Message {
32 | oneof sum {
33 | BlockRequest block_request = 1;
34 | NoBlockResponse no_block_response = 2;
35 | BlockResponse block_response = 3;
36 | StatusRequest status_request = 4;
37 | StatusResponse status_response = 5;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/spec/consensus/proposer-based-timestamp/tla/typedefs.tla:
--------------------------------------------------------------------------------
1 | -------------------- MODULE typedefs ---------------------------
2 | (*
3 | @typeAlias: PROCESS = Str;
4 | @typeAlias: VALUE = Str;
5 | @typeAlias: STEP = Str;
6 | @typeAlias: ROUND = Int;
7 | @typeAlias: ACTION = Str;
8 | @typeAlias: TRACE = Seq(Str);
9 | @typeAlias: TIME = Int;
10 | @typeAlias: PROPOSAL = <>;
11 | @typeAlias: DECISION = <>;
12 | @typeAlias: RCVPROP = <>;
13 | @typeAlias: PROPMESSAGE =
14 | [
15 | type: STEP,
16 | src: PROCESS,
17 | round: ROUND,
18 | proposal: PROPOSAL,
19 | validRound: ROUND
20 | ];
21 | @typeAlias: PREMESSAGE =
22 | [
23 | type: STEP,
24 | src: PROCESS,
25 | round: ROUND,
26 | id: PROPOSAL
27 | ];
28 | @typeAlias: MESSAGE =
29 | [
30 | type: STEP,
31 | src: PROCESS,
32 | round: ROUND,
33 | proposal: PROPOSAL,
34 | validRound: ROUND,
35 | id: PROPOSAL
36 | ];
37 | *)
38 | TypeAliases == TRUE
39 |
40 | =============================================================================
--------------------------------------------------------------------------------
/spec/light-client/accountability/TendermintAccTrace_004_draft.tla:
--------------------------------------------------------------------------------
1 | ------------------ MODULE TendermintAccTrace_004_draft -------------------------
2 | (*
3 | When Apalache is running too slow and we have an idea of a counterexample,
4 | we use this module to restrict the behaviors only to certain actions.
5 | Once the whole trace is replayed, the system deadlocks.
6 |
7 | Version 1.
8 |
9 | Igor Konnov, 2020.
10 | *)
11 |
12 | EXTENDS Sequences, Apalache, TendermintAcc_004_draft
13 |
14 | \* a sequence of action names that should appear in the given order,
15 | \* excluding "Init"
16 | CONSTANT
17 | \* @type: TRACE;
18 | Trace
19 |
20 | VARIABLE
21 | \* @type: TRACE;
22 | toReplay
23 |
24 | TraceInit ==
25 | /\ toReplay = Trace
26 | /\ action' := "Init"
27 | /\ Init
28 |
29 | TraceNext ==
30 | /\ Len(toReplay) > 0
31 | /\ toReplay' = Tail(toReplay)
32 | \* Here is the trick. We restrict the action to the expected one,
33 | \* so the other actions will be pruned
34 | /\ action' := Head(toReplay)
35 | /\ Next
36 |
37 | ================================================================================
38 |
--------------------------------------------------------------------------------
/spec/abci/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | parent:
4 | title: ABCI
5 | order: 2
6 | ---
7 |
8 | # ABCI
9 |
10 | ABCI stands for "**A**pplication **B**lock**c**hain **I**nterface".
11 | ABCI is the interface between Tendermint (a state-machine replication engine)
12 | and your application (the actual state machine). It consists of a set of
13 | _methods_, each with a corresponding `Request` and `Response`message type.
14 | To perform state-machine replication, Tendermint calls the ABCI methods on the
15 | ABCI application by sending the `Request*` messages and receiving the `Response*` messages in return.
16 |
17 | All ABCI messages and methods are defined in [protocol buffers](../../proto/tendermint/abci/types.proto).
18 | This allows Tendermint to run with applications written in many programming languages.
19 |
20 | This specification is split as follows:
21 |
22 | - [Methods and Types](./abci.md) - complete details on all ABCI methods and
23 | message types
24 | - [Applications](./apps.md) - how to manage ABCI application state and other
25 | details about building ABCI applications
26 | - [Client and Server](./client-server.md) - for those looking to implement their
27 | own ABCI application servers
28 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/proposal.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Protocol Change Proposal
3 | about: Create a proposal to request a change to the protocol
4 |
5 | ---
6 |
7 |
12 |
13 | # Protocol Change Proposal
14 |
15 | ## Summary
16 |
17 |
18 |
19 | ## Problem Definition
20 |
21 |
25 |
26 | ## Proposal
27 |
28 |
29 |
30 | ____
31 |
32 | #### For Admin Use
33 |
34 | - [ ] Not duplicate issue
35 | - [ ] Appropriate labels applied
36 | - [ ] Appropriate contributors tagged
37 | - [ ] Contributor assigned/self-assigned
38 |
--------------------------------------------------------------------------------
/spec/p2p/messages/mempool.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 4
3 | ---
4 | # Mempool
5 |
6 | ## Channel
7 |
8 | Mempool has one channel. The channel identifier is listed below.
9 |
10 | | Name | Number |
11 | |----------------|--------|
12 | | MempoolChannel | 48 |
13 |
14 | ## Message Types
15 |
16 | There is currently only one message that Mempool broadcasts and receives over
17 | the p2p gossip network (via the reactor): `TxsMessage`
18 |
19 | ### Txs
20 |
21 | A list of transactions. These transactions have been checked against the application for validity. This does not mean that the transactions are valid, it is up to the application to check this.
22 |
23 | | Name | Type | Description | Field Number |
24 | |------|----------------|----------------------|--------------|
25 | | txs | repeated bytes | List of transactions | 1 |
26 |
27 | ### Message
28 |
29 | Message is a [`oneof` protobuf type](https://developers.google.com/protocol-buffers/docs/proto#oneof). The one of consists of one message [`Txs`](#txs).
30 |
31 | | Name | Type | Description | Field Number |
32 | |------|-------------|-----------------------|--------------|
33 | | txs | [Txs](#txs) | List of transactions | 1 |
34 |
--------------------------------------------------------------------------------
/spec/consensus/consensus-paper/homodel.sty:
--------------------------------------------------------------------------------
1 | \newcommand{\NC}{\mbox{\it NC}}
2 | \newcommand{\HO}{\mbox{\it HO}}
3 | \newcommand{\AS}{\mbox{\it AS}}
4 | \newcommand{\SK}{\mbox{\it SK}}
5 | \newcommand{\SHO}{\mbox{\it SHO}}
6 | \newcommand{\AHO}{\mbox{\it AHO}}
7 | \newcommand{\CONS}{\mbox{\it CONS}}
8 | \newcommand{\K}{\mbox{\it K}}
9 |
10 | \newcommand{\Alg}{\mathcal{A}}
11 | \newcommand{\Pred}{\mathcal{P}}
12 | \newcommand{\Spr}{S_p^r}
13 | \newcommand{\Tpr}{T_p^r}
14 | \newcommand{\mupr}{\vec{\mu}_p^{\,r}}
15 |
16 | \newcommand{\MSpr}{S_p^{\rho}}
17 | \newcommand{\MTpr}{T_p^{\rho}}
18 |
19 |
20 |
21 | \newconstruct{\SEND}{$\Spr$:}{}{\ENDSEND}{}
22 | \newconstruct{\TRAN}{$\Tpr$:}{}{\ENDTRAN}{}
23 | \newconstruct{\ROUND}{\textbf{Round}}{\!\textbf{:}}{\ENDROUND}{}
24 | \newconstruct{\VARIABLES}{\textbf{Variables:}}{}{\ENDVARIABLES}{}
25 | \newconstruct{\INIT}{\textbf{Initialization:}}{}{\ENDINIT}{}
26 |
27 | \newconstruct{\MSEND}{$\MSpr$:}{}{\ENDMSEND}{}
28 | \newconstruct{\MTRAN}{$\MTpr$:}{}{\ENDMTRAN}{}
29 |
30 | \newconstruct{\SROUND}{\textbf{Selection Round}}{\!\textbf{:}}{\ENDSROUND}{}
31 | \newconstruct{\VROUND}{\textbf{Validation Round}}{\!\textbf{:}}{\ENDVROUND}{}
32 | \newconstruct{\DROUND}{\textbf{Decision Round}}{\!\textbf{:}}{\ENDDROUND}{}
33 |
--------------------------------------------------------------------------------
/spec/consensus/consensus-paper/conclusion.tex:
--------------------------------------------------------------------------------
1 | \section{Conclusion} \label{sec:conclusion}
2 |
3 | We have proposed a new Byzantine-fault tolerant consensus algorithm that is the
4 | core of the Tendermint BFT SMR platform. The algorithm is designed for the wide
5 | area network with high number of mutually distrusted nodes that communicate
6 | over gossip based peer-to-peer network. It has only a single mode of execution
7 | and the communication pattern is very similar to the "normal" case of the
8 | state-of-the art PBFT algorithm. The algorithm ensures termination with a novel
9 | mechanism that takes advantage of the gossip based communication between nodes.
10 | The proposed algorithm and the proofs are simple and elegant, and we believe
11 | that this makes it easier to understand and implement correctly.
12 |
13 | \section*{Acknowledgment}
14 |
15 | We would like to thank Anton Kaliaev, Ismail Khoffi and Dahlia Malkhi for comments on an earlier version of the paper. We also want to thank Marko Vukolic, Ming Chuan Lin, Maria Potop-Butucaru, Sara Tucci, Antonella Del Pozzo and Yackolley Amoussou-Guenou for pointing out the liveness issues
16 | in the previous version of the algorithm. Finally, we want to thank the Tendermint team members and all project contributors for making Tendermint such a great platform.
17 |
--------------------------------------------------------------------------------
/spec/light-client/accountability/MC_n4_f1.tla:
--------------------------------------------------------------------------------
1 | ----------------------------- MODULE MC_n4_f1 -------------------------------
2 | CONSTANT
3 | \* @type: ROUND -> PROCESS;
4 | Proposer
5 |
6 | \* the variables declared in TendermintAcc3
7 | VARIABLES
8 | \* @type: PROCESS -> ROUND;
9 | round,
10 | \* @type: PROCESS -> STEP;
11 | step,
12 | \* @type: PROCESS -> VALUE;
13 | decision,
14 | \* @type: PROCESS -> VALUE;
15 | lockedValue,
16 | \* @type: PROCESS -> ROUND;
17 | lockedRound,
18 | \* @type: PROCESS -> VALUE;
19 | validValue,
20 | \* @type: PROCESS -> ROUND;
21 | validRound,
22 | \* @type: ROUND -> Set(PROPMESSAGE);
23 | msgsPropose,
24 | \* @type: ROUND -> Set(PREMESSAGE);
25 | msgsPrevote,
26 | \* @type: ROUND -> Set(PREMESSAGE);
27 | msgsPrecommit,
28 | \* @type: Set(MESSAGE);
29 | evidence,
30 | \* @type: ACTION;
31 | action
32 |
33 | INSTANCE TendermintAccDebug_004_draft WITH
34 | Corr <- {"c1", "c2", "c3"},
35 | Faulty <- {"f1"},
36 | N <- 4,
37 | T <- 1,
38 | ValidValues <- { "v0", "v1" },
39 | InvalidValues <- {"v2"},
40 | MaxRound <- 2
41 |
42 | \* run Apalache with --cinit=ConstInit
43 | ConstInit == \* the proposer is arbitrary -- works for safety
44 | Proposer \in [Rounds -> AllProcs]
45 |
46 | =============================================================================
47 |
--------------------------------------------------------------------------------
/spec/light-client/accountability/MC_n4_f2.tla:
--------------------------------------------------------------------------------
1 | ----------------------------- MODULE MC_n4_f2 -------------------------------
2 | CONSTANT
3 | \* @type: ROUND -> PROCESS;
4 | Proposer
5 |
6 | \* the variables declared in TendermintAcc3
7 | VARIABLES
8 | \* @type: PROCESS -> ROUND;
9 | round,
10 | \* @type: PROCESS -> STEP;
11 | step,
12 | \* @type: PROCESS -> VALUE;
13 | decision,
14 | \* @type: PROCESS -> VALUE;
15 | lockedValue,
16 | \* @type: PROCESS -> ROUND;
17 | lockedRound,
18 | \* @type: PROCESS -> VALUE;
19 | validValue,
20 | \* @type: PROCESS -> ROUND;
21 | validRound,
22 | \* @type: ROUND -> Set(PROPMESSAGE);
23 | msgsPropose,
24 | \* @type: ROUND -> Set(PREMESSAGE);
25 | msgsPrevote,
26 | \* @type: ROUND -> Set(PREMESSAGE);
27 | msgsPrecommit,
28 | \* @type: Set(MESSAGE);
29 | evidence,
30 | \* @type: ACTION;
31 | action
32 |
33 | INSTANCE TendermintAccDebug_004_draft WITH
34 | Corr <- {"c1", "c2"},
35 | Faulty <- {"f3", "f4"},
36 | N <- 4,
37 | T <- 1,
38 | ValidValues <- { "v0", "v1" },
39 | InvalidValues <- {"v2"},
40 | MaxRound <- 2
41 |
42 | \* run Apalache with --cinit=ConstInit
43 | ConstInit == \* the proposer is arbitrary -- works for safety
44 | Proposer \in [Rounds -> AllProcs]
45 |
46 | =============================================================================
47 |
--------------------------------------------------------------------------------
/spec/light-client/accountability/MC_n4_f3.tla:
--------------------------------------------------------------------------------
1 | ----------------------------- MODULE MC_n4_f3 -------------------------------
2 | CONSTANT
3 | \* @type: ROUND -> PROCESS;
4 | Proposer
5 |
6 | \* the variables declared in TendermintAcc3
7 | VARIABLES
8 | \* @type: PROCESS -> ROUND;
9 | round,
10 | \* @type: PROCESS -> STEP;
11 | step,
12 | \* @type: PROCESS -> VALUE;
13 | decision,
14 | \* @type: PROCESS -> VALUE;
15 | lockedValue,
16 | \* @type: PROCESS -> ROUND;
17 | lockedRound,
18 | \* @type: PROCESS -> VALUE;
19 | validValue,
20 | \* @type: PROCESS -> ROUND;
21 | validRound,
22 | \* @type: ROUND -> Set(PROPMESSAGE);
23 | msgsPropose,
24 | \* @type: ROUND -> Set(PREMESSAGE);
25 | msgsPrevote,
26 | \* @type: ROUND -> Set(PREMESSAGE);
27 | msgsPrecommit,
28 | \* @type: Set(MESSAGE);
29 | evidence,
30 | \* @type: ACTION;
31 | action
32 |
33 | INSTANCE TendermintAccDebug_004_draft WITH
34 | Corr <- {"c1"},
35 | Faulty <- {"f2", "f3", "f4"},
36 | N <- 4,
37 | T <- 1,
38 | ValidValues <- { "v0", "v1" },
39 | InvalidValues <- {"v2"},
40 | MaxRound <- 2
41 |
42 | \* run Apalache with --cinit=ConstInit
43 | ConstInit == \* the proposer is arbitrary -- works for safety
44 | Proposer \in [Rounds -> AllProcs]
45 |
46 | =============================================================================
47 |
--------------------------------------------------------------------------------
/spec/light-client/accountability/MC_n5_f1.tla:
--------------------------------------------------------------------------------
1 | ----------------------------- MODULE MC_n5_f1 -------------------------------
2 | CONSTANT
3 | \* @type: ROUND -> PROCESS;
4 | Proposer
5 |
6 | \* the variables declared in TendermintAcc3
7 | VARIABLES
8 | \* @type: PROCESS -> ROUND;
9 | round,
10 | \* @type: PROCESS -> STEP;
11 | step,
12 | \* @type: PROCESS -> VALUE;
13 | decision,
14 | \* @type: PROCESS -> VALUE;
15 | lockedValue,
16 | \* @type: PROCESS -> ROUND;
17 | lockedRound,
18 | \* @type: PROCESS -> VALUE;
19 | validValue,
20 | \* @type: PROCESS -> ROUND;
21 | validRound,
22 | \* @type: ROUND -> Set(PROPMESSAGE);
23 | msgsPropose,
24 | \* @type: ROUND -> Set(PREMESSAGE);
25 | msgsPrevote,
26 | \* @type: ROUND -> Set(PREMESSAGE);
27 | msgsPrecommit,
28 | \* @type: Set(MESSAGE);
29 | evidence,
30 | \* @type: ACTION;
31 | action
32 |
33 | INSTANCE TendermintAccDebug_004_draft WITH
34 | Corr <- {"c1", "c2", "c3", "c4"},
35 | Faulty <- {"f5"},
36 | N <- 5,
37 | T <- 1,
38 | ValidValues <- { "v0", "v1" },
39 | InvalidValues <- {"v2"},
40 | MaxRound <- 2
41 |
42 | \* run Apalache with --cinit=ConstInit
43 | ConstInit == \* the proposer is arbitrary -- works for safety
44 | Proposer \in [Rounds -> AllProcs]
45 |
46 | =============================================================================
47 |
--------------------------------------------------------------------------------
/spec/light-client/accountability/MC_n5_f2.tla:
--------------------------------------------------------------------------------
1 | ----------------------------- MODULE MC_n5_f2 -------------------------------
2 | CONSTANT
3 | \* @type: ROUND -> PROCESS;
4 | Proposer
5 |
6 | \* the variables declared in TendermintAcc3
7 | VARIABLES
8 | \* @type: PROCESS -> ROUND;
9 | round,
10 | \* @type: PROCESS -> STEP;
11 | step,
12 | \* @type: PROCESS -> VALUE;
13 | decision,
14 | \* @type: PROCESS -> VALUE;
15 | lockedValue,
16 | \* @type: PROCESS -> ROUND;
17 | lockedRound,
18 | \* @type: PROCESS -> VALUE;
19 | validValue,
20 | \* @type: PROCESS -> ROUND;
21 | validRound,
22 | \* @type: ROUND -> Set(PROPMESSAGE);
23 | msgsPropose,
24 | \* @type: ROUND -> Set(PREMESSAGE);
25 | msgsPrevote,
26 | \* @type: ROUND -> Set(PREMESSAGE);
27 | msgsPrecommit,
28 | \* @type: Set(MESSAGE);
29 | evidence,
30 | \* @type: ACTION;
31 | action
32 |
33 | INSTANCE TendermintAccDebug_004_draft WITH
34 | Corr <- {"c1", "c2", "c3"},
35 | Faulty <- {"f4", "f5"},
36 | N <- 5,
37 | T <- 1,
38 | ValidValues <- { "v0", "v1" },
39 | InvalidValues <- {"v2"},
40 | MaxRound <- 2
41 |
42 | \* run Apalache with --cinit=ConstInit
43 | ConstInit == \* the proposer is arbitrary -- works for safety
44 | Proposer \in [Rounds -> AllProcs]
45 |
46 | =============================================================================
47 |
--------------------------------------------------------------------------------
/spec/light-client/accountability/MC_n6_f1.tla:
--------------------------------------------------------------------------------
1 | ----------------------------- MODULE MC_n6_f1 -------------------------------
2 | CONSTANT
3 | \* @type: ROUND -> PROCESS;
4 | Proposer
5 |
6 | \* the variables declared in TendermintAcc3
7 | VARIABLES
8 | \* @type: PROCESS -> ROUND;
9 | round,
10 | \* @type: PROCESS -> STEP;
11 | step,
12 | \* @type: PROCESS -> VALUE;
13 | decision,
14 | \* @type: PROCESS -> VALUE;
15 | lockedValue,
16 | \* @type: PROCESS -> ROUND;
17 | lockedRound,
18 | \* @type: PROCESS -> VALUE;
19 | validValue,
20 | \* @type: PROCESS -> ROUND;
21 | validRound,
22 | \* @type: ROUND -> Set(PROPMESSAGE);
23 | msgsPropose,
24 | \* @type: ROUND -> Set(PREMESSAGE);
25 | msgsPrevote,
26 | \* @type: ROUND -> Set(PREMESSAGE);
27 | msgsPrecommit,
28 | \* @type: Set(MESSAGE);
29 | evidence,
30 | \* @type: ACTION;
31 | action
32 |
33 | INSTANCE TendermintAccDebug_004_draft WITH
34 | Corr <- {"c1", "c2", "c3", "c4", "c5"},
35 | Faulty <- {"f6"},
36 | N <- 4,
37 | T <- 1,
38 | ValidValues <- { "v0", "v1" },
39 | InvalidValues <- {"v2"},
40 | MaxRound <- 2
41 |
42 | \* run Apalache with --cinit=ConstInit
43 | ConstInit == \* the proposer is arbitrary -- works for safety
44 | Proposer \in [Rounds -> AllProcs]
45 |
46 | =============================================================================
47 |
--------------------------------------------------------------------------------
/spec/light-client/detection/LCD_MC3_3_faulty.tla:
--------------------------------------------------------------------------------
1 | ------------------------- MODULE LCD_MC3_3_faulty ---------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 3
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == FALSE
10 | IS_SECONDARY_CORRECT == TRUE
11 | FAULTY_RATIO == <<2, 3>> \* < 1 / 3 faulty validators
12 |
13 | VARIABLES
14 | blockchain, (* the reference blockchain *)
15 | localClock, (* current time in the light client *)
16 | refClock, (* current time in the reference blockchain *)
17 | Faulty, (* the set of faulty validators *)
18 | state, (* the state of the light client detector *)
19 | fetchedLightBlocks1, (* a function from heights to LightBlocks *)
20 | fetchedLightBlocks2, (* a function from heights to LightBlocks *)
21 | fetchedLightBlocks1b, (* a function from heights to LightBlocks *)
22 | commonHeight, (* the height that is trusted in CreateEvidenceForPeer *)
23 | nextHeightToTry, (* the index in CreateEvidenceForPeer *)
24 | evidences
25 |
26 | INSTANCE LCDetector_003_draft
27 | ============================================================================
28 |
--------------------------------------------------------------------------------
/spec/light-client/detection/LCD_MC3_4_faulty.tla:
--------------------------------------------------------------------------------
1 | ------------------------- MODULE LCD_MC3_4_faulty ---------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 4
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == FALSE
10 | IS_SECONDARY_CORRECT == TRUE
11 | FAULTY_RATIO == <<2, 3>> \* < 1 / 3 faulty validators
12 |
13 | VARIABLES
14 | blockchain, (* the reference blockchain *)
15 | localClock, (* current time in the light client *)
16 | refClock, (* current time in the reference blockchain *)
17 | Faulty, (* the set of faulty validators *)
18 | state, (* the state of the light client detector *)
19 | fetchedLightBlocks1, (* a function from heights to LightBlocks *)
20 | fetchedLightBlocks2, (* a function from heights to LightBlocks *)
21 | fetchedLightBlocks1b, (* a function from heights to LightBlocks *)
22 | commonHeight, (* the height that is trusted in CreateEvidenceForPeer *)
23 | nextHeightToTry, (* the index in CreateEvidenceForPeer *)
24 | evidences
25 |
26 | INSTANCE LCDetector_003_draft
27 | ============================================================================
28 |
--------------------------------------------------------------------------------
/spec/light-client/detection/LCD_MC4_4_faulty.tla:
--------------------------------------------------------------------------------
1 | ------------------------- MODULE LCD_MC4_4_faulty ---------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 4
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == FALSE
10 | IS_SECONDARY_CORRECT == TRUE
11 | FAULTY_RATIO == <<2, 3>> \* < 2 / 3 faulty validators
12 |
13 | VARIABLES
14 | blockchain, (* the reference blockchain *)
15 | localClock, (* current time in the light client *)
16 | refClock, (* current time in the reference blockchain *)
17 | Faulty, (* the set of faulty validators *)
18 | state, (* the state of the light client detector *)
19 | fetchedLightBlocks1, (* a function from heights to LightBlocks *)
20 | fetchedLightBlocks2, (* a function from heights to LightBlocks *)
21 | fetchedLightBlocks1b, (* a function from heights to LightBlocks *)
22 | commonHeight, (* the height that is trusted in CreateEvidenceForPeer *)
23 | nextHeightToTry, (* the index in CreateEvidenceForPeer *)
24 | evidences
25 |
26 | INSTANCE LCDetector_003_draft
27 | ============================================================================
28 |
--------------------------------------------------------------------------------
/spec/light-client/detection/LCD_MC5_5_faulty.tla:
--------------------------------------------------------------------------------
1 | ------------------------- MODULE LCD_MC5_5_faulty ---------------------------
2 |
3 | AllNodes == {"n1", "n2", "n3", "n4", "n5"}
4 | TRUSTED_HEIGHT == 1
5 | TARGET_HEIGHT == 5
6 | TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-)
7 | CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting
8 | REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting
9 | IS_PRIMARY_CORRECT == FALSE
10 | IS_SECONDARY_CORRECT == TRUE
11 | FAULTY_RATIO == <<2, 3>> \* < 1 / 3 faulty validators
12 |
13 | VARIABLES
14 | blockchain, (* the reference blockchain *)
15 | localClock, (* current time in the light client *)
16 | refClock, (* current time in the reference blockchain *)
17 | Faulty, (* the set of faulty validators *)
18 | state, (* the state of the light client detector *)
19 | fetchedLightBlocks1, (* a function from heights to LightBlocks *)
20 | fetchedLightBlocks2, (* a function from heights to LightBlocks *)
21 | fetchedLightBlocks1b, (* a function from heights to LightBlocks *)
22 | commonHeight, (* the height that is trusted in CreateEvidenceForPeer *)
23 | nextHeightToTry, (* the index in CreateEvidenceForPeer *)
24 | evidences
25 |
26 | INSTANCE LCDetector_003_draft
27 | ============================================================================
28 |
--------------------------------------------------------------------------------
/ivy-proofs/Dockerfile:
--------------------------------------------------------------------------------
1 | # we need python2 support, which was dropped after buster:
2 | FROM debian:buster
3 |
4 | RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
5 | RUN apt-get update
6 | RUN apt-get install -y apt-utils
7 |
8 | # Install and configure locale `en_US.UTF-8`
9 | RUN apt-get install -y locales && \
10 | sed -i -e "s/# $en_US.*/en_US.UTF-8 UTF-8/" /etc/locale.gen && \
11 | dpkg-reconfigure --frontend=noninteractive locales && \
12 | update-locale LANG=en_US.UTF-8
13 | ENV LANG=en_US.UTF-8
14 |
15 | RUN apt-get update
16 | RUN apt-get install -y git python2 python-pip g++ cmake python-ply python-tk tix pkg-config libssl-dev python-setuptools
17 |
18 | # create a user:
19 | RUN useradd -ms /bin/bash user
20 | USER user
21 | WORKDIR /home/user
22 |
23 | RUN git clone --recurse-submodules https://github.com/kenmcmil/ivy.git
24 | WORKDIR /home/user/ivy/
25 | RUN git checkout 271ee38980699115508eb90a0dd01deeb750a94b
26 |
27 | RUN python2.7 build_submodules.py
28 | RUN mkdir -p "/home/user/python/lib/python2.7/site-packages"
29 | ENV PYTHONPATH="/home/user/python/lib/python2.7/site-packages"
30 | # need to install pyparsing manually because otherwise wrong version found
31 | RUN pip install pyparsing
32 | RUN python2.7 setup.py install --prefix="/home/user/python/"
33 | ENV PATH=$PATH:"/home/user/python/bin/"
34 | WORKDIR /home/user/tendermint-proof/
35 |
36 | ENTRYPOINT ["/home/user/tendermint-proof/check_proofs.sh"]
37 |
38 |
--------------------------------------------------------------------------------
/proto/tendermint/p2p/types.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package tendermint.p2p;
3 |
4 | import "gogoproto/gogo.proto";
5 | import "google/protobuf/timestamp.proto";
6 |
7 | message ProtocolVersion {
8 | uint64 p2p = 1 [(gogoproto.customname) = "P2P"];
9 | uint64 block = 2;
10 | uint64 app = 3;
11 | }
12 |
13 | message NodeInfo {
14 | ProtocolVersion protocol_version = 1 [(gogoproto.nullable) = false];
15 | string node_id = 2 [(gogoproto.customname) = "NodeID"];
16 | string listen_addr = 3;
17 | string network = 4;
18 | string version = 5;
19 | bytes channels = 6;
20 | string moniker = 7;
21 | NodeInfoOther other = 8 [(gogoproto.nullable) = false];
22 | }
23 |
24 | message NodeInfoOther {
25 | string tx_index = 1;
26 | string rpc_address = 2 [(gogoproto.customname) = "RPCAddress"];
27 | }
28 |
29 | message PeerInfo {
30 | string id = 1 [(gogoproto.customname) = "ID"];
31 | repeated PeerAddressInfo address_info = 2;
32 | google.protobuf.Timestamp last_connected = 3 [(gogoproto.stdtime) = true];
33 | }
34 |
35 | message PeerAddressInfo {
36 | string address = 1;
37 | google.protobuf.Timestamp last_dial_success = 2
38 | [(gogoproto.stdtime) = true];
39 | google.protobuf.Timestamp last_dial_failure = 3
40 | [(gogoproto.stdtime) = true];
41 | uint32 dial_failures = 4;
42 | }
43 |
--------------------------------------------------------------------------------
/spec/consensus/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | parent:
4 | title: Consensus
5 | order: 4
6 | ---
7 |
8 | **THIS REPOSITORY HAS BEEN ARCHIVED. THE TENDERMINT SPECIFICATION IS NOW LOCATED IN THE [TENDERMINT/TENDERMINT](https://github.com/tendermint/tendermint/tree/master/spec) REPOSITORY.**
9 |
10 | ---
11 |
12 | # Consensus
13 |
14 | Specification of the Tendermint consensus protocol.
15 |
16 | ## Contents
17 |
18 | - [Consensus Paper](./consensus-paper) - Latex paper on
19 | [arxiv](https://arxiv.org/abs/1807.04938) describing the
20 | core Tendermint consensus state machine with proofs of safety and termination.
21 | - [BFT Time](./bft-time.md) - How the timestamp in a Tendermint
22 | block header is computed in a Byzantine Fault Tolerant manner
23 | - [Creating Proposal](./creating-proposal.md) - How a proposer
24 | creates a block proposal for consensus
25 | - [Light Client Protocol](./light-client) - A protocol for light weight consensus
26 | verification and syncing to the latest state
27 | - [Signing](./signing.md) - Rules for cryptographic signatures
28 | produced by validators.
29 | - [Write Ahead Log](./wal.md) - Write ahead log used by the
30 | consensus state machine to recover from crashes.
31 |
32 | The protocol used to gossip consensus messages between peers, which is critical
33 | for liveness, is described in the [reactors section](./consensus.md).
34 |
35 | There is also a [stale markdown description](consensus.md) of the consensus state machine
36 | (TODO update this).
37 |
--------------------------------------------------------------------------------
/rfc/rfc_template.md:
--------------------------------------------------------------------------------
1 | # RFC {RFC-NUMBER}: {TITLE}
2 |
3 | ## Changelog
4 |
5 | - {date}: {changelog}
6 |
7 | ## Author(s)
8 |
9 | - {First Name} {github handle}
10 |
11 | ## Context
12 |
13 | > This section contains all the context one needs to understand the current state, and why there is a problem. It should be as succinct as possible and introduce the high level idea behind the solution.
14 |
15 | ## Proposal
16 |
17 | > It should contain a detailed breakdown of how the problem should be resolved including diagrams and other supporting materials needed to present the case and implementation roadmap for the proposed changes. The reader should be able to fully understand the proposal. This section should be broken up using ## subsections as needed.
18 |
19 | ## Status
20 |
21 | > A decision may be "proposed" if it hasn't been agreed upon yet, or "accepted" once it is agreed upon. If a later RFC changes or reverses a decision, it may be marked as "deprecated" or "superseded" with a reference to its replacement.
22 |
23 | {Deprecated|Proposed|Accepted}
24 |
25 | ## Consequences
26 |
27 | > This section describes the consequences, after applying the decision. All consequences should be summarized here, not just the "positive" ones.
28 |
29 | ### Positive
30 |
31 | ### Negative
32 |
33 | ### Neutral
34 |
35 | ## References
36 |
37 | > Are there any relevant PR comments, issues that led up to this, or articles referenced for why we made the given design choice? If so link them here!
38 |
39 | - {reference link}
40 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # The Docker image containing the generator, formatter, and linter.
2 | # This is generated by proto/Dockerfile. To update tools, make changes
3 | # there and run the Build & Push Proto Builder Image workflow.
4 | IMAGE := ghcr.io/tendermint/docker-build-proto:latest
5 | DOCKER_PROTO_BUILDER := docker run -v $(shell pwd):/workspace --workdir /workspace $(IMAGE)
6 | HTTPS_GIT := https://github.com/tendermint/spec.git
7 |
8 | ###############################################################################
9 | ### Protobuf ###
10 | ###############################################################################
11 |
12 | proto-all: proto-lint proto-check-breaking
13 | .PHONY: proto-all
14 |
15 | proto-gen:
16 | @echo "Generating Protobuf files"
17 | @$(DOCKER_PROTO_BUILDER) buf generate --template=./buf.gen.yaml --config ./buf.yaml
18 | .PHONY: proto-gen
19 |
20 | proto-lint:
21 | @$(DOCKER_PROTO_BUILDER) buf lint --error-format=json --config ./buf.yaml
22 | .PHONY: proto-lint
23 |
24 | proto-format:
25 | @echo "Formatting Protobuf files"
26 | @$(DOCKER_PROTO_BUILDER) find . -name '*.proto' -path "./proto/*" -exec clang-format -i {} \;
27 | .PHONY: proto-format
28 |
29 | proto-check-breaking:
30 | @$(DOCKER_PROTO_BUILDER) buf breaking --against .git --config ./buf.yaml
31 | .PHONY: proto-check-breaking
32 |
33 | proto-check-breaking-ci:
34 | @$(DOCKER_PROTO_BUILDER) buf breaking --against $(HTTPS_GIT) --config ./buf.yaml
35 | .PHONY: proto-check-breaking-ci
36 |
--------------------------------------------------------------------------------
/spec/consensus/wal.md:
--------------------------------------------------------------------------------
1 | # WAL
2 |
3 | Consensus module writes every message to the WAL (write-ahead log).
4 |
5 | It also issues fsync syscall through
6 | [File#Sync](https://golang.org/pkg/os/#File.Sync) for messages signed by this
7 | node (to prevent double signing).
8 |
9 | Under the hood, it uses
10 | [autofile.Group](https://godoc.org/github.com/tendermint/tmlibs/autofile#Group),
11 | which rotates files when those get too big (> 10MB).
12 |
13 | The total maximum size is 1GB. We only need the latest block and the block before it,
14 | but if the former is dragging on across many rounds, we want all those rounds.
15 |
16 | ## Replay
17 |
18 | Consensus module will replay all the messages of the last height written to WAL
19 | before a crash (if such occurs).
20 |
21 | The private validator may try to sign messages during replay because it runs
22 | somewhat autonomously and does not know about replay process.
23 |
24 | For example, if we got all the way to precommit in the WAL and then crash,
25 | after we replay the proposal message, the private validator will try to sign a
26 | prevote. But it will fail. That's ok because we’ll see the prevote later in the
27 | WAL. Then it will go to precommit, and that time it will work because the
28 | private validator contains the `LastSignBytes` and then we’ll replay the
29 | precommit from the WAL.
30 |
31 | Make sure to read about [WAL corruption](https://github.com/tendermint/tendermint/blob/master/docs/tendermint-core/running-in-production.md#wal-corruption)
32 | and recovery strategies.
33 |
--------------------------------------------------------------------------------
/spec/consensus/creating-proposal.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 2
3 | ---
4 | # Creating a proposal
5 |
6 | A block consists of a header, transactions, votes (the commit),
7 | and a list of evidence of malfeasance (ie. signing conflicting votes).
8 |
9 | We include no more than 1/10th of the maximum block size
10 | (`ConsensusParams.Block.MaxBytes`) of evidence with each block.
11 |
12 | ## Reaping transactions from the mempool
13 |
14 | When we reap transactions from the mempool, we calculate maximum data
15 | size by subtracting maximum header size (`MaxHeaderBytes`), the maximum
16 | amino overhead for a block (`MaxAminoOverheadForBlock`), the size of
17 | the last commit (if present) and evidence (if present). While reaping
18 | we account for amino overhead for each transaction.
19 |
20 | ```go
21 | func MaxDataBytes(maxBytes int64, valsCount, evidenceCount int) int64 {
22 | return maxBytes -
23 | MaxOverheadForBlock -
24 | MaxHeaderBytes -
25 | int64(valsCount)*MaxVoteBytes -
26 | int64(evidenceCount)*MaxEvidenceBytes
27 | }
28 | ```
29 |
30 | ## Validating transactions in the mempool
31 |
32 | Before we accept a transaction in the mempool, we check if it's size is no more
33 | than {MaxDataSize}. {MaxDataSize} is calculated using the same formula as
34 | above, except we subtract the max number of evidence, {MaxNum} by the maximum size of evidence
35 |
36 | ```go
37 | func MaxDataBytesUnknownEvidence(maxBytes int64, valsCount int) int64 {
38 | return maxBytes -
39 | MaxOverheadForBlock -
40 | MaxHeaderBytes -
41 | (maxNumEvidence * MaxEvidenceBytes)
42 | }
43 | ```
44 |
--------------------------------------------------------------------------------
/rfc/README.md:
--------------------------------------------------------------------------------
1 | **THIS REPOSITORY HAS BEEN ARCHIVED. THE TENDERMINT SPECIFICATION IS NOW LOCATED IN THE [TENDERMINT/TENDERMINT](https://github.com/tendermint/tendermint/tree/master/spec) REPOSITORY.**
2 |
3 | ---
4 |
5 | # Request for Comments (RFC)
6 |
7 | RFC stands for `Request for Comments`. It is a social device use to float and polish an idea prior to the inclusion into an existing or new spec/paper/research topic.
8 |
9 | An RFC should not be used for bug reports or trivial discussions - the overhead of compiling an RFC does not justify it.
10 |
11 | An RFC should not consist only of a problem statement (use a standard issue for that).
12 |
13 | A RFC should consist of:
14 |
15 | - Changelog
16 | - Context on the relevant goals and the current state
17 | - Proposed Solution
18 | - Summary of pros and cons
19 | - References
20 |
21 | If recorded decisions turned out to be lacking, convene a discussion, record the new decisions here, and then modify the code to match.
22 |
23 | **Note the context/background should be written in the present tense.**
24 |
25 | Some RFC's will be presented at a Tendermint Dev Session. If you are an outside contributor and have submitted a RFC, you may be invited to present your RFC at one of these calls.
26 |
27 | ## Table of Contents
28 |
29 | - [001-block-retention](./001-block-retention.md)
30 | - [002-nonzero-genesis](./002-nonzero-genesis.md)
31 | - [003-ed25519-verification](./003-ed25519-verification.md)
32 | - [004-abci++](./004-abci++.md)
33 | - [005-reverse-sync](./005-reverse-sync.md)
34 | - [006-semantic-versioning](./006-semantic-versioning.md)
35 |
--------------------------------------------------------------------------------
/proto/tendermint/types/evidence.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package tendermint.types;
3 |
4 | import "gogoproto/gogo.proto";
5 | import "google/protobuf/timestamp.proto";
6 | import "tendermint/types/types.proto";
7 | import "tendermint/types/validator.proto";
8 |
9 | message Evidence {
10 | oneof sum {
11 | DuplicateVoteEvidence duplicate_vote_evidence = 1;
12 | LightClientAttackEvidence light_client_attack_evidence = 2;
13 | }
14 | }
15 |
16 | // DuplicateVoteEvidence contains evidence of a validator signed two conflicting
17 | // votes.
18 | message DuplicateVoteEvidence {
19 | tendermint.types.Vote vote_a = 1;
20 | tendermint.types.Vote vote_b = 2;
21 | int64 total_voting_power = 3;
22 | int64 validator_power = 4;
23 | google.protobuf.Timestamp timestamp = 5
24 | [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
25 | }
26 |
27 | // LightClientAttackEvidence contains evidence of a set of validators attempting
28 | // to mislead a light client.
29 | message LightClientAttackEvidence {
30 | tendermint.types.LightBlock conflicting_block = 1;
31 | int64 common_height = 2;
32 | repeated tendermint.types.Validator byzantine_validators = 3;
33 | int64 total_voting_power = 4;
34 | google.protobuf.Timestamp timestamp = 5
35 | [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
36 | }
37 |
38 | message EvidenceList {
39 | repeated Evidence evidence = 1 [(gogoproto.nullable) = false];
40 | }
41 |
--------------------------------------------------------------------------------
/proto/tendermint/statesync/types.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package tendermint.statesync;
3 |
4 | import "gogoproto/gogo.proto";
5 | import "tendermint/types/types.proto";
6 | import "tendermint/types/params.proto";
7 |
8 | message Message {
9 | oneof sum {
10 | SnapshotsRequest snapshots_request = 1;
11 | SnapshotsResponse snapshots_response = 2;
12 | ChunkRequest chunk_request = 3;
13 | ChunkResponse chunk_response = 4;
14 | LightBlockRequest light_block_request = 5;
15 | LightBlockResponse light_block_response = 6;
16 | ParamsRequest params_request = 7;
17 | ParamsResponse params_response = 8;
18 | }
19 | }
20 |
21 | message SnapshotsRequest {}
22 |
23 | message SnapshotsResponse {
24 | uint64 height = 1;
25 | uint32 format = 2;
26 | uint32 chunks = 3;
27 | bytes hash = 4;
28 | bytes metadata = 5;
29 | }
30 |
31 | message ChunkRequest {
32 | uint64 height = 1;
33 | uint32 format = 2;
34 | uint32 index = 3;
35 | }
36 |
37 | message ChunkResponse {
38 | uint64 height = 1;
39 | uint32 format = 2;
40 | uint32 index = 3;
41 | bytes chunk = 4;
42 | bool missing = 5;
43 | }
44 |
45 | message LightBlockRequest {
46 | uint64 height = 1;
47 | }
48 |
49 | message LightBlockResponse {
50 | tendermint.types.LightBlock light_block = 1;
51 | }
52 |
53 | message ParamsRequest {
54 | uint64 height = 1;
55 | }
56 |
57 | message ParamsResponse {
58 | uint64 height = 1;
59 | tendermint.types.ConsensusParams consensus_params = 2
60 | [(gogoproto.nullable) = false];
61 | }
62 |
--------------------------------------------------------------------------------
/spec/light-client/accountability/MC_n4_f2_amnesia.tla:
--------------------------------------------------------------------------------
1 | ---------------------- MODULE MC_n4_f2_amnesia -------------------------------
2 | EXTENDS Sequences
3 |
4 | CONSTANT
5 | \* @type: ROUND -> PROCESS;
6 | Proposer
7 |
8 | \* the variables declared in TendermintAcc3
9 | VARIABLES
10 | \* @type: PROCESS -> ROUND;
11 | round,
12 | \* @type: PROCESS -> STEP;
13 | step,
14 | \* @type: PROCESS -> VALUE;
15 | decision,
16 | \* @type: PROCESS -> VALUE;
17 | lockedValue,
18 | \* @type: PROCESS -> ROUND;
19 | lockedRound,
20 | \* @type: PROCESS -> VALUE;
21 | validValue,
22 | \* @type: PROCESS -> ROUND;
23 | validRound,
24 | \* @type: ROUND -> Set(PROPMESSAGE);
25 | msgsPropose,
26 | \* @type: ROUND -> Set(PREMESSAGE);
27 | msgsPrevote,
28 | \* @type: ROUND -> Set(PREMESSAGE);
29 | msgsPrecommit,
30 | \* @type: Set(MESSAGE);
31 | evidence,
32 | \* @type: ACTION;
33 | action
34 |
35 | \* the variable declared in TendermintAccTrace3
36 | VARIABLE
37 | \* @type: TRACE;
38 | toReplay
39 |
40 | INSTANCE TendermintAccTrace_004_draft WITH
41 | Corr <- {"c1", "c2"},
42 | Faulty <- {"f3", "f4"},
43 | N <- 4,
44 | T <- 1,
45 | ValidValues <- { "v0", "v1" },
46 | InvalidValues <- {"v2"},
47 | MaxRound <- 2,
48 | Trace <- <<
49 | "UponProposalInPropose",
50 | "UponProposalInPrevoteOrCommitAndPrevote",
51 | "UponProposalInPrecommitNoDecision",
52 | "OnRoundCatchup",
53 | "UponProposalInPropose",
54 | "UponProposalInPrevoteOrCommitAndPrevote",
55 | "UponProposalInPrecommitNoDecision"
56 | >>
57 |
58 | \* run Apalache with --cinit=ConstInit
59 | ConstInit == \* the proposer is arbitrary -- works for safety
60 | Proposer \in [Rounds -> AllProcs]
61 |
62 | =============================================================================
63 |
--------------------------------------------------------------------------------
/proto/README.md:
--------------------------------------------------------------------------------
1 | # Protocol Buffers
2 |
3 | This sections defines the types and messages shared across implementations. The definition of the data structures are located in the [core/data_structures](../spec/core/data_structures.md) for the core data types and ABCI definitions are located in the [ABCI](../spec/abci/README.md) section.
4 |
5 | ## Process of Updates
6 |
7 | The `.proto` files within this section are core to the protocol and updates must be treated as such.
8 |
9 | ### Steps
10 |
11 | 1. Make an issue with the proposed change.
12 | - Within in the issue members from both the Tendermint-go and Tendermint-rs team will leave comments. If there is not consensus on the change an [RFC](../rfc/README.md) may be requested.
13 | 1a. Submission of an RFC as a pull request should be made to facilitate further discussion.
14 | 1b. Merge the RFC.
15 | 2. Make the necessary changes to the `.proto` file(s), [core data structures](../spec/core/data_structures.md) and/or [ABCI protocol](../spec/abci/apps.md).
16 | 3. Open issues within Tendermint-go and Tendermint-rs repos. This is used to notify the teams that a change occurred in the spec.
17 | 1. Tag the issue with a spec version label. This will notify the team the changed has been made on master but has not entered a release.
18 |
19 | ### Versioning
20 |
21 | The spec repo aims to be versioned. Once it has been versioned, updates to the protobuf files will live on master. After a certain amount of time, decided on by Tendermint-go and Tendermint-rs team leads, a release will be made on the spec repo. The spec may contain minor releases as well, depending on the implementation these changes may lead to a breaking change. If so, the implementation team should open an issue within the spec repo requiring a major release of the spec.
22 |
23 | If the steps above were followed each implementation should have issues tagged with a spec change label. Once all issues have been completed the team should signify their readiness for release.
24 |
--------------------------------------------------------------------------------
/spec/p2p/messages/pex.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 6
3 | ---
4 |
5 | # Peer Exchange
6 |
7 | ## Channels
8 |
9 | Pex has one channel. The channel identifier is listed below.
10 |
11 | | Name | Number |
12 | |------------|--------|
13 | | PexChannel | 0 |
14 |
15 | ## Message Types
16 |
17 | ### PexRequest
18 |
19 | PexRequest is an empty message requesting a list of peers.
20 |
21 | > EmptyRequest
22 |
23 | ### PexResponse
24 |
25 | PexResponse is an list of net addresses provided to a peer to dial.
26 |
27 | | Name | Type | Description | Field Number |
28 | |-------|------------------------------------|------------------------------------------|--------------|
29 | | addresses | repeated [PexAddress](#PexAddress) | List of peer addresses available to dial | 1 |
30 |
31 | ### PexAddress
32 |
33 | PexAddress provides needed information for a node to dial a peer. This is in the form of a `URL` that gets parsed
34 | into a `NodeAddress`. See [ParseNodeAddress](https://github.com/tendermint/tendermint/blob/f2a8f5e054cf99ebe246818bb6d71f41f9a30faa/internal/p2p/address.go#L43) for more details.
35 |
36 | | Name | Type | Description | Field Number |
37 | |------|--------|------------------|--------------|
38 | | url | string | See [golang url](https://golang.org/pkg/net/url/#URL) | 1 |
39 |
40 | ### Message
41 |
42 | Message is a [`oneof` protobuf type](https://developers.google.com/protocol-buffers/docs/proto#oneof). The one of consists of two messages.
43 |
44 | | Name | Type | Description | Field Number |
45 | |--------------|---------------------------|------------------------------------------------------|--------------|
46 | | pex_request | [PexRequest](#PexRequest) | Empty request asking for a list of addresses to dial | 3 |
47 | | pex_response | [PexResponse](#PexResponse) | List of addresses to dial | 4 |
48 |
--------------------------------------------------------------------------------
/spec/light-client/supervisor/supervisor_001_draft.tla:
--------------------------------------------------------------------------------
1 | ------------------------- MODULE supervisor_001_draft ------------------------
2 | (*
3 | This is the beginning of a spec that will eventually use verification and detector API
4 | *)
5 |
6 | EXTENDS Integers, FiniteSets
7 |
8 | VARIABLES
9 | state,
10 | output
11 |
12 | vars == <>
13 |
14 | CONSTANT
15 | INITDATA
16 |
17 | Init ==
18 | /\ state = "Init"
19 | /\ output = "none"
20 |
21 | NextInit ==
22 | /\ state = "Init"
23 | /\ \/ state' = "EnterLoop"
24 | \/ state' = "FailedToInitialize"
25 | /\ UNCHANGED output
26 |
27 | NextVerifyToTarget ==
28 | /\ state = "EnterLoop"
29 | /\ \/ state' = "EnterLoop" \* replace primary
30 | \/ state' = "EnterDetect"
31 | \/ state' = "ExhaustedPeersPrimary"
32 | /\ UNCHANGED output
33 |
34 | NextAttackDetector ==
35 | /\ state = "EnterDetect"
36 | /\ \/ state' = "NoEvidence"
37 | \/ state' = "EvidenceFound"
38 | \/ state' = "ExhaustedPeersSecondaries"
39 | /\ UNCHANGED output
40 |
41 | NextVerifyAndDetect ==
42 | \/ NextVerifyToTarget
43 | \/ NextAttackDetector
44 |
45 | NextOutput ==
46 | /\ state = "NoEvidence"
47 | /\ state' = "EnterLoop"
48 | /\ output' = "data" \* to generate a trace
49 |
50 | NextTerminated ==
51 | /\ \/ state = "FailedToInitialize"
52 | \/ state = "ExhaustedPeersPrimary"
53 | \/ state = "EvidenceFound"
54 | \/ state = "ExhaustedPeersSecondaries"
55 | /\ UNCHANGED vars
56 |
57 | Next ==
58 | \/ NextInit
59 | \/ NextVerifyAndDetect
60 | \/ NextOutput
61 | \/ NextTerminated
62 |
63 | InvEnoughPeers ==
64 | /\ state /= "ExhaustedPeersPrimary"
65 | /\ state /= "ExhaustedPeersSecondaries"
66 |
67 |
68 | =============================================================================
69 | \* Modification History
70 | \* Last modified Sun Oct 18 11:48:45 CEST 2020 by widder
71 | \* Created Sun Oct 18 11:18:53 CEST 2020 by widder
72 |
--------------------------------------------------------------------------------
/ivy-proofs/README.md:
--------------------------------------------------------------------------------
1 | # Ivy Proofs
2 |
3 | ```copyright
4 | Copyright (c) 2020 Galois, Inc.
5 | SPDX-License-Identifier: Apache-2.0
6 | ```
7 |
8 | ## Contents
9 |
10 | This folder contains:
11 |
12 | * `tendermint.ivy`, a specification of Tendermint algorithm as described in *The latest gossip on BFT consensus* by E. Buchman, J. Kwon, Z. Milosevic.
13 | * `abstract_tendermint.ivy`, a more abstract specification of Tendermint that is more verification-friendly.
14 | * `classic_safety.ivy`, a proof that Tendermint satisfies the classic safety property of BFT consensus: if every two quorums have a well-behaved node in common, then no two well-behaved nodes ever disagree.
15 | * `accountable_safety_1.ivy`, a proof that, assuming every quorum contains at least one well-behaved node, if two well-behaved nodes disagree, then there is evidence demonstrating at least f+1 nodes misbehaved.
16 | * `accountable_safety_2.ivy`, a proof that, regardless of any assumption about quorums, well-behaved nodes cannot be framed by malicious nodes. In other words, malicious nodes can never construct evidence that incriminates a well-behaved node.
17 | * `network_shim.ivy`, the network model and a convenience `shim` object to interface with the Tendermint specification.
18 | * `domain_model.ivy`, a specification of the domain model underlying the Tendermint specification, i.e. rounds, value, quorums, etc.
19 |
20 | All specifications and proofs are written in [Ivy](https://github.com/kenmcmil/ivy).
21 |
22 | The license above applies to all files in this folder.
23 |
24 |
25 | ## Building and running
26 |
27 | The easiest way to check the proofs is to use [Docker](https://www.docker.com/).
28 |
29 | 1. Install [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/).
30 | 2. Build a Docker image: `docker-compose build`
31 | 3. Run the proofs inside the Docker container: `docker-compose run
32 | tendermint-proof`. This will check all the proofs with the `ivy_check`
33 | command and write the output of `ivy_check` to a subdirectory of `./output/'
34 |
--------------------------------------------------------------------------------
/spec/consensus/consensus-paper/rounddiag.sty:
--------------------------------------------------------------------------------
1 | % ROUNDDIAG STYLE
2 | % for LaTeX version 2e
3 | % by -- 2008 Martin Hutle
4 | %
5 | % This style file is free software; you can redistribute it and/or
6 | % modify it under the terms of the GNU Lesser General Public
7 | % License as published by the Free Software Foundation; either
8 | % version 2 of the License, or (at your option) any later version.
9 | %
10 | % This style file is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | % Lesser General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU Lesser General Public
16 | % License along with this style file; if not, write to the
17 | % Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 | % Boston, MA 02111-1307, USA.
19 | %
20 | \NeedsTeXFormat{LaTeX2e}
21 | \ProvidesPackage{rounddiag}
22 | \typeout{Document Style `rounddiag' - provides simple round diagrams}
23 | %
24 | \RequirePackage{ifthen}
25 | \RequirePackage{calc}
26 | \RequirePackage{tikz}
27 |
28 | \def\rdstretch{3}
29 |
30 | \tikzstyle{msg}=[->,thick,>=latex]
31 | \tikzstyle{rndline}=[dotted]
32 | \tikzstyle{procline}=[dotted]
33 |
34 | \newenvironment{rounddiag}[2]{
35 | \begin{center}
36 | \begin{tikzpicture}
37 | \foreach \i in {1,...,#1}{
38 | \draw[procline] (0,#1-\i) node[xshift=-1em]{$p_{\i}$} -- (#2*\rdstretch+1,#1-\i);
39 | }
40 | \foreach \i in {0,...,#2}{
41 | \draw[rndline] (\i*\rdstretch+0.5,0) -- (\i*\rdstretch+0.5,#1-1);
42 | }
43 | \newcommand{\rdat}[2]{
44 | (##2*\rdstretch+0.5,#1-##1)
45 | }%
46 | \newcommand{\round}[2]{%
47 | \def\rdround{##1}
48 | \ifthenelse{\equal{##2}{}}{}{
49 | \node[yshift=-1em] at ({##1*\rdstretch+0.5-0.5*\rdstretch},0) {##2};
50 | }
51 | }%
52 | \newcommand{\rdmessage}[3]{\draw[msg]
53 | (\rdround*\rdstretch-\rdstretch+0.5,#1-##1) -- node[yshift=1.2ex]{##3}
54 | (\rdround*\rdstretch+0.5,#1-##2);}%
55 | \newcommand{\rdalltoall}{%
56 | \foreach \i in {1,...,#1}{
57 | \foreach \j in {1,...,#1}{
58 | { \rdmessage{\i}{\j}{}}}}}%
59 | }{%
60 | \end{tikzpicture}
61 | \end{center}
62 | }
63 |
--------------------------------------------------------------------------------
/spec/p2p/config.md:
--------------------------------------------------------------------------------
1 | # P2P Config
2 |
3 | Here we describe configuration options around the Peer Exchange.
4 | These can be set using flags or via the `$TMHOME/config/config.toml` file.
5 |
6 | ## Seed Mode
7 |
8 | `--p2p.seed_mode`
9 |
10 | The node operates in seed mode. In seed mode, a node continuously crawls the network for peers,
11 | and upon incoming connection shares some peers and disconnects.
12 |
13 | ## Seeds
14 |
15 | `--p2p.seeds “id100000000000000000000000000000000@1.2.3.4:26656,id200000000000000000000000000000000@2.3.4.5:4444”`
16 |
17 | Dials these seeds when we need more peers. They should return a list of peers and then disconnect.
18 | If we already have enough peers in the address book, we may never need to dial them.
19 |
20 | ## Persistent Peers
21 |
22 | `--p2p.persistent_peers “id100000000000000000000000000000000@1.2.3.4:26656,id200000000000000000000000000000000@2.3.4.5:26656”`
23 |
24 | Dial these peers and auto-redial them if the connection fails.
25 | These are intended to be trusted persistent peers that can help
26 | anchor us in the p2p network. The auto-redial uses exponential
27 | backoff and will give up after a day of trying to connect.
28 |
29 | But If `persistent_peers_max_dial_period` is set greater than zero,
30 | pause between each dial to each persistent peer will not exceed `persistent_peers_max_dial_period`
31 | during exponential backoff and we keep trying again without giving up
32 |
33 | **Note:** If `seeds` and `persistent_peers` intersect,
34 | the user will be warned that seeds may auto-close connections
35 | and that the node may not be able to keep the connection persistent.
36 |
37 | ## Private Peers
38 |
39 | `--p2p.private_peer_ids “id100000000000000000000000000000000,id200000000000000000000000000000000”`
40 |
41 | These are IDs of the peers that we do not add to the address book or gossip to
42 | other peers. They stay private to us.
43 |
44 | ## Unconditional Peers
45 |
46 | `--p2p.unconditional_peer_ids “id100000000000000000000000000000000,id200000000000000000000000000000000”`
47 |
48 | These are IDs of the peers which are allowed to be connected by both inbound or outbound regardless of
49 | `max_num_inbound_peers` or `max_num_outbound_peers` of user's node reached or not.
50 |
--------------------------------------------------------------------------------
/.github/workflows/proto-dockerfile.yml:
--------------------------------------------------------------------------------
1 | # This workflow (re)builds and pushes a Docker image containing the
2 | # protobuf build tools used by the other workflows.
3 | #
4 | # When making changes that require updates to the builder image, you
5 | # should merge the updates first and wait for this workflow to complete,
6 | # so that the changes will be available for the dependent workflows.
7 | #
8 |
9 | name: Build & Push Proto Builder Image
10 | on:
11 | pull_request:
12 | paths:
13 | - "proto/*"
14 | push:
15 | branches:
16 | - master
17 | paths:
18 | - "proto/*"
19 | schedule:
20 | # run this job once a month to recieve any go or buf updates
21 | - cron: "0 9 1 * *"
22 |
23 | env:
24 | REGISTRY: ghcr.io
25 | IMAGE_NAME: tendermint/docker-build-proto
26 |
27 | jobs:
28 | build:
29 | runs-on: ubuntu-latest
30 | steps:
31 | - uses: actions/checkout@v2.4.0
32 | - name: Check out and assign tags
33 | id: prep
34 | run: |
35 | DOCKER_IMAGE="${REGISTRY}/${IMAGE_NAME}"
36 | VERSION=noop
37 | if [[ "$GITHUB_REF" == "refs/tags/*" ]]; then
38 | VERSION="${GITHUB_REF#refs/tags/}"
39 | elif [[ "$GITHUB_REF" == "refs/heads/*" ]]; then
40 | VERSION="$(echo "${GITHUB_REF#refs/heads/}" | sed -r 's#/+#-#g')"
41 | if [[ "${{ github.event.repository.default_branch }}" = "$VERSION" ]]; then
42 | VERSION=latest
43 | fi
44 | fi
45 | TAGS="${DOCKER_IMAGE}:${VERSION}"
46 | echo ::set-output name=tags::"${TAGS}"
47 |
48 | - name: Set up docker buildx
49 | uses: docker/setup-buildx-action@v1.6.0
50 |
51 | - name: Log in to the container registry
52 | uses: docker/login-action@v1.12.0
53 | with:
54 | registry: ${{ env.REGISTRY }}
55 | username: ${{ github.actor }}
56 | password: ${{ secrets.GITHUB_TOKEN }}
57 |
58 | - name: Build and publish image
59 | uses: docker/build-push-action@v2.9.0
60 | with:
61 | context: ./proto
62 | file: ./proto/Dockerfile
63 | push: ${{ github.event_name != 'pull_request' }}
64 | tags: ${{ steps.prep.outputs.tags }}
65 |
--------------------------------------------------------------------------------
/spec/abci++/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | parent:
4 | title: ABCI++
5 | order: 3
6 | ---
7 |
8 | **THIS REPOSITORY HAS BEEN ARCHIVED. THE TENDERMINT SPECIFICATION IS NOW LOCATED IN THE [TENDERMINT/TENDERMINT](https://github.com/tendermint/tendermint/tree/master/spec) REPOSITORY.**
9 |
10 | ---
11 |
12 | # ABCI++
13 |
14 | ## Introduction
15 |
16 | ABCI++ is a major evolution of ABCI (**A**pplication **B**lock**c**hain **I**nterface).
17 | Like its predecessor, ABCI++ is the interface between Tendermint (a state-machine
18 | replication engine) and the actual state machine being replicated (i.e., the Application).
19 | The API consists of a set of _methods_, each with a corresponding `Request` and `Response`
20 | message type.
21 |
22 | The methods are always initiated by Tendermint. The Application implements its logic
23 | for handling all ABCI++ methods.
24 | Thus, Tendermint always sends the `Request*` messages and receives the `Response*` messages
25 | in return.
26 |
27 | All ABCI++ messages and methods are defined in
28 | [protocol buffers](https://github.com/tendermint/spec/blob/master/proto/tendermint/abci/types.proto).
29 | This allows Tendermint to run with applications written in many programming languages.
30 |
31 | This specification is split as follows:
32 |
33 | - [Basic concepts and definitions](./abci++_basic_concepts_002_draft.md) - definitions and descriptions
34 | of concepts that are needed to understand other parts of this sepcification.
35 | - [Methods](./abci++_methods_002_draft.md) - complete details on all ABCI++ methods
36 | and message types.
37 | - [Requirements for the Application](./abci++_app_requirements_002_draft.md) - formal requirements
38 | on the Application's logic to ensure liveness of Tendermint. These requirements define what
39 | Tendermint expects from the Application.
40 | - [Tendermint's expected behavior](./abci++_tmint_expected_behavior_002_draft.md) - specification of
41 | how the different ABCI++ methods may be called by Tendermint. This explains what the Application
42 | is to expect from Tendermint.
43 |
44 | >**TODO** Re-read these and remove redundant info
45 |
46 | - [Applications](../abci/apps.md) - how to manage ABCI application state and other
47 | details about building ABCI applications
48 | - [Client and Server](../abci/client-server.md) - for those looking to implement their
49 | own ABCI application servers
50 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | **THIS REPOSITORY HAS BEEN ARCHIVED. THE TENDERMINT SPECIFICATION IS NOW LOCATED IN THE [TENDERMINT/TENDERMINT](https://github.com/tendermint/tendermint/tree/master/spec) REPOSITORY.**
2 |
3 | ---
4 |
5 | # Tendermint Spec
6 |
7 | This repository contains specifications for the Tendermint protocol.
8 |
9 | There are currently two implementations of the Tendermint protocol,
10 | maintained by two separate-but-collaborative entities:
11 | One in [Go](https://github.com/tendermint/tendermint),
12 | maintained by Interchain GmbH,
13 | and one in [Rust](https://github.com/informalsystems/tendermint-rs),
14 | maintained by Informal Systems.
15 |
16 | ### Data Structures
17 |
18 | - [Encoding and Digests](./spec/core/encoding.md)
19 | - [Blockchain](./spec/core/data_structures.md)
20 | - [State](./spec/core/state.md)
21 |
22 | ### Consensus Protocol
23 |
24 | - [Consensus Algorithm](./spec/consensus/consensus.md)
25 | - [Creating a proposal](./spec/consensus/creating-proposal.md)
26 | - [Time](./spec/consensus/bft-time.md)
27 | - [Light-Client](./spec/consensus/light-client/README.md)
28 |
29 | ### P2P and Network Protocols
30 |
31 | - [The Base P2P Layer](./spec/p2p/node.md): multiplex the protocols ("reactors") on authenticated and encrypted TCP connections
32 |
33 | #### P2P Messages
34 |
35 | - [Peer Exchange (PEX)](./spec/p2p/messages/pex.md): gossip known peer addresses so peers can find each other
36 | - [Block Sync](./spec/p2p/messages/block-sync.md): gossip blocks so peers can catch up quickly
37 | - [Consensus](./spec/p2p/messages/consensus.md): gossip votes and block parts so new blocks can be committed
38 | - [Mempool](./spec/p2p/messages/mempool.md): gossip transactions so they get included in blocks
39 | - [Evidence](./spec/p2p/messages/evidence.md): sending invalid evidence will stop the peer
40 |
41 | ### ABCI
42 |
43 | - [ABCI](./spec/abci/README.md): Details about interactions between the
44 | application and consensus engine over ABCI
45 |
46 | ### ABCI++
47 |
48 | - [ABCI++](./spec/abci++/README.md): Specification of interactions between the
49 | application and consensus engine over ABCI++
50 |
51 | ### RFC
52 |
53 | - [RFC](./rfc/README.md): RFCs describe proposals to change the spec.
54 |
55 | ### ProtoBuf
56 |
57 | - [Proto](./proto/README.md): The data structures of the Tendermint protocol are located in the `proto` directory. These specify P2P messages that each implementation should follow to be compatible.
58 |
--------------------------------------------------------------------------------
/spec/core/genesis.md:
--------------------------------------------------------------------------------
1 | # Genesis
2 |
3 | The genesis file is the starting point of a chain. An application will populate the `app_state` field in the genesis with their required fields. Tendermint is not able to validate this section because it is unaware what application state consists of.
4 |
5 | ## Genesis Fields
6 |
7 | - `genesis_time`: The genesis time is the time the blockchain started or will start. If nodes are started before this time they will sit idle until the time specified.
8 | - `chain_id`: The chainid is the chain identifier. Every chain should have a unique identifier. When conducting a fork based upgrade, we recommend changing the chainid to avoid network or consensus errors.
9 | - `initial_height`: This field is the starting height of the blockchain. When conducting a chain restart to avoid restarting at height 1, the network is able to start at a specified height.
10 | - `consensus_params`
11 | - `block`
12 | - `max_bytes`: The max amount of bytes a block can be.
13 | - `max_gas`: The maximum amount of gas that a block can have.
14 | - `time_iota_ms`: This parameter has no value anymore in Tendermint-core.
15 |
16 | - `evidence`
17 | - `max_age_num_blocks`: After this preset amount of blocks has passed a single piece of evidence is considered invalid
18 | - `max_age_duration`: After this preset amount of time has passed a single piece of evidence is considered invalid.
19 | - `max_bytes`: The max amount of bytes of all evidence included in a block.
20 |
21 | > Note: For evidence to be considered invalid, evidence must be older than both `max_age_num_blocks` and `max_age_duration`
22 |
23 | - `validator`
24 | - `pub_key_types`: Defines which curves are to be accepted as a valid validator consensus key. Tendermint supports ed25519, sr25519 and secp256k1.
25 |
26 | - `version`
27 | - `app_version`: The version of the application. This is set by the application and is used to identify which version of the app a user should be using in order to operate a node.
28 |
29 | - `validators`
30 | - This is an array of validators. This validator set is used as the starting validator set of the chain. This field can be empty, if the application sets the validator set in `InitChain`.
31 |
32 | - `app_hash`: The applications state root hash. This field does not need to be populated at the start of the chain, the application may provide the needed information via `Initchain`.
33 |
34 | - `app_state`: This section is filled in by the application and is unknown to Tendermint.
35 |
--------------------------------------------------------------------------------
/spec/light-client/detection/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | parent:
4 | title: Fork Detection
5 | order: 2
6 | ---
7 |
8 | **THIS REPOSITORY HAS BEEN ARCHIVED. THE TENDERMINT SPECIFICATION IS NOW LOCATED IN THE [TENDERMINT/TENDERMINT](https://github.com/tendermint/tendermint/tree/master/spec) REPOSITORY.**
9 |
10 | ---
11 |
12 | # Tendermint fork detection and IBC fork detection
13 |
14 | ## Status
15 |
16 | This is a work in progress.
17 | This directory captures the ongoing work and discussion on fork
18 | detection both in the context of a Tendermint light node and in the
19 | context of IBC. It contains the following files
20 |
21 | ### detection.md
22 |
23 | a draft of the light node fork detection including "proof of fork"
24 | definition, that is, the data structure to submit evidence to full
25 | nodes.
26 |
27 | ### [discussions.md](./discussions.md)
28 |
29 | A collection of ideas and intuitions from recent discussions
30 |
31 | - the outcome of recent discussion
32 | - a sketch of the light client supervisor to provide the context in
33 | which fork detection happens
34 | - a discussion about lightstore semantics
35 |
36 | ### [req-ibc-detection.md](./req-ibc-detection.md)
37 |
38 | - a collection of requirements for fork detection in the IBC
39 | context. In particular it contains a section "Required Changes in
40 | ICS 007" with necessary updates to ICS 007 to support Tendermint
41 | fork detection
42 |
43 | ### [draft-functions.md](./draft-functions.md)
44 |
45 | In order to address the collected requirements, we started to sketch
46 | some functions that we will need in the future when we specify in more
47 | detail the
48 |
49 | - fork detections
50 | - proof of fork generation
51 | - proof of fork verification
52 |
53 | on the following components.
54 |
55 | - IBC on-chain components
56 | - Relayer
57 |
58 | ### TODOs
59 |
60 | We decided to merge the files while there are still open points to
61 | address to record the current state an move forward. In particular,
62 | the following points need to be addressed:
63 |
64 | -
65 |
66 | -
67 |
68 | -
69 |
70 | -
71 |
72 | Most likely we will write a specification on the light client
73 | supervisor along the outcomes of
74 |
75 | -
76 |
77 | that also addresses initialization
78 |
79 | -
80 |
--------------------------------------------------------------------------------
/spec/light-client/verification/verification_003_draft.md:
--------------------------------------------------------------------------------
1 | # Light Client Verificaiton
2 |
3 | #### **[LCV-FUNC-VERIFYCOMMITLIGHT.1]**
4 |
5 | VerifyCommitLight verifies that 2/3+ of the signatures for a validator set were for
6 | a given blockID. The function will finish early and thus may not check all signatures.
7 |
8 | ```go
9 | func VerifyCommitLight(chainID string, vals *ValidatorSet, blockID BlockID,
10 | height int64, commit *Commit) error {
11 | // run a basic validation of the arguments
12 | if err := verifyBasicValsAndCommit(vals, commit, height, blockID); err != nil {
13 | return err
14 | }
15 |
16 | // calculate voting power needed
17 | votingPowerNeeded := vals.TotalVotingPower() * 2 / 3
18 |
19 | var (
20 | val *Validator
21 | valIdx int32
22 | seenVals = make(map[int32]int, len(commit.Signatures))
23 | talliedVotingPower int64 = 0
24 | voteSignBytes []byte
25 | )
26 | for idx, commitSig := range commit.Signatures {
27 | // ignore all commit signatures that are not for the block
28 | if !commitSig.ForBlock() {
29 | continue
30 | }
31 |
32 | // If the vals and commit have a 1-to-1 correspondance we can retrieve
33 | // them by index else we need to retrieve them by address
34 | if lookUpByIndex {
35 | val = vals.Validators[idx]
36 | } else {
37 | valIdx, val = vals.GetByAddress(commitSig.ValidatorAddress)
38 |
39 | // if the signature doesn't belong to anyone in the validator set
40 | // then we just skip over it
41 | if val == nil {
42 | continue
43 | }
44 |
45 | // because we are getting validators by address we need to make sure
46 | // that the same validator doesn't commit twice
47 | if firstIndex, ok := seenVals[valIdx]; ok {
48 | secondIndex := idx
49 | return fmt.Errorf("double vote from %v (%d and %d)", val, firstIndex, secondIndex)
50 | }
51 | seenVals[valIdx] = idx
52 | }
53 |
54 | voteSignBytes = commit.VoteSignBytes(chainID, int32(idx))
55 |
56 | if !val.PubKey.VerifySignature(voteSignBytes, commitSig.Signature) {
57 | return fmt.Errorf("wrong signature (#%d): %X", idx, commitSig.Signature)
58 | }
59 |
60 | // Add the voting power of the validator
61 | // to the tally
62 | talliedVotingPower += val.VotingPower
63 |
64 | // check if we have enough signatures and can thus exit early
65 | if talliedVotingPower > votingPowerNeeded {
66 | return nil
67 | }
68 | }
69 |
70 | if got, needed := talliedVotingPower, votingPowerNeeded; got <= needed {
71 | return ErrNotEnoughVotingPowerSigned{Got: got, Needed: needed}
72 | }
73 |
74 | return nil
75 | }
76 | ```
--------------------------------------------------------------------------------
/ivy-proofs/accountable_safety_2.ivy:
--------------------------------------------------------------------------------
1 | #lang ivy1.7
2 |
3 | include tendermint
4 | include abstract_tendermint
5 |
6 | # Here we prove the second accountability property: no well-behaved node is
7 | # ever observed to violate the accountability properties.
8 |
9 | # The proof is done in two steps: first we prove the the abstract specification
10 | # satisfies the property, and then we show by refinement that this property
11 | # also holds in the concrete specification.
12 |
13 | # To see what is checked in the refinement proof, use `ivy_show isolate=accountable_safety_2 accountable_safety_2.ivy`
14 | # To see what is checked in the abstract correctness proof, use `ivy_show isolate=abstract_accountable_safety_2 accountable_safety_2.ivy`
15 | # To check the whole proof, use `ivy_check complete=fo accountable_safety_2.ivy`.
16 |
17 | # Proof that the property holds in the abstract specification
18 | # ============================================================
19 |
20 | isolate abstract_accountable_safety_2 = {
21 |
22 | instantiate abstract_tendermint
23 |
24 | # the main property:
25 | invariant [wb_never_punished] well_behaved(N) -> ~(observed_equivocation(N) | observed_unlawful_prevote(N))
26 |
27 | # the main invariant for proving wb_not_punished:
28 | invariant well_behaved(N) & precommitted(N,R,V) & ~locked(N,R,V) & V ~= value.nil -> exists R2,V2 . V2 ~= value.nil & R < R2 & precommitted(N,R2,V2) & locked(N,R2,V2)
29 |
30 | invariant (exists N . well_behaved(N) & precommitted(N,R,V) & V ~= value.nil) -> exists Q . nset.is_quorum(Q) & forall N . nset.member(N,Q) -> observed_prevoted(N,R,V)
31 |
32 | invariant well_behaved(N) -> (observed_prevoted(N,R,V) <-> prevoted(N,R,V))
33 | invariant well_behaved(N) -> (observed_precommitted(N,R,V) <-> precommitted(N,R,V))
34 |
35 | # nodes stop prevoting or precommitting in lower rounds when doing so in a higher round:
36 | invariant well_behaved(N) & prevoted(N,R2,V2) & R1 < R2 -> left_round(N,R1)
37 | invariant well_behaved(N) & locked(N,R2,V2) & R1 < R2 -> left_round(N,R1)
38 |
39 | invariant [precommit_unique_per_round] well_behaved(N) & precommitted(N,R,V1) & precommitted(N,R,V2) -> V1 = V2
40 |
41 | } with nset, round, abstract_accountable_safety_2.defs.observed_equivocation_def, abstract_accountable_safety_2.defs.observed_unlawful_prevote_def
42 |
43 | # Proof that the property holds in the concrete specification
44 | # ===========================================================
45 |
46 | isolate accountable_safety_2 = {
47 |
48 | instantiate tendermint(abstract_accountable_safety_2)
49 |
50 | invariant well_behaved(N) -> ~(abstract_accountable_safety_2.observed_equivocation(N) | abstract_accountable_safety_2.observed_unlawful_prevote(N))
51 |
52 | } with round, value, shim, abstract_accountable_safety_2, abstract_accountable_safety_2.defs.observed_equivocation_def, abstract_accountable_safety_2.defs.observed_unlawful_prevote_def
53 |
--------------------------------------------------------------------------------
/rfc/003-ed25519-verification.md:
--------------------------------------------------------------------------------
1 | # RFC 003: Ed25519 Verification
2 |
3 | ## Changelog
4 |
5 | - August 21, 2020: initialized
6 |
7 | ## Author(s)
8 |
9 | - Marko (@marbar3778)
10 |
11 | ## Context
12 |
13 | Ed25519 keys are the only supported key types for Tendermint validators currently. Tendermint-Go wraps the ed25519 key implementation from the go standard library. As more clients are implemented to communicate with the canonical Tendermint implementation (Tendermint-Go) different implementations of ed25519 will be used. Due to [RFC 8032](https://www.rfc-editor.org/rfc/rfc8032.html) not guaranteeing implementation compatibility, Tendermint clients must to come to an agreement of how to guarantee implementation compatibility. [Zcash](https://z.cash/) has multiple implementations of their client and have identified this as a problem as well. The team at Zcash has made a proposal to address this issue, [Zcash improvement proposal 215](https://zips.z.cash/zip-0215).
14 |
15 | ## Proposal
16 |
17 | - Tendermint-Go would adopt [hdevalence/ed25519consensus](https://github.com/hdevalence/ed25519consensus).
18 | - This library is implements `ed25519.Verify()` in accordance to zip-215. Tendermint-go will continue to use `crypto/ed25519` for signing and key generation.
19 |
20 | - Tendermint-rs would adopt [ed25519-zebra](https://github.com/ZcashFoundation/ed25519-zebra)
21 | - related [issue](https://github.com/informalsystems/tendermint-rs/issues/355)
22 |
23 | Signature verification is one of the major bottlenecks of Tendermint-go, batch verification can not be used unless it has the same consensus rules, ZIP 215 makes verification safe in consensus critical areas.
24 |
25 | This change constitutes a breaking changes, therefore must be done in a major release. No changes to validator keys or operations will be needed for this change to be enabled.
26 |
27 | This change has no impact on signature aggregation. To enable this signature aggregation Tendermint will have to use different signature schema (Schnorr, BLS, ...). Secondly, this change will enable safe batch verification for the Tendermint-Go client. Batch verification for the rust client is already supported in the library being used.
28 |
29 | As part of the acceptance of this proposal it would be best to contract or discuss with a third party the process of conducting a security review of the go library.
30 |
31 | ## Status
32 |
33 | Proposed
34 |
35 | ## Consequences
36 |
37 | ### Positive
38 |
39 | - Consistent signature verification across implementations
40 | - Enable safe batch verification
41 |
42 | ### Negative
43 |
44 | #### Tendermint-Go
45 |
46 | - Third_party dependency
47 | - library has not gone through a security review.
48 | - unclear maintenance schedule
49 | - Fragmentation of the ed25519 key for the go implementation, verification is done using a third party library while the rest
50 | uses the go standard library
51 |
52 | ### Neutral
53 |
54 | ## References
55 |
56 | [It’s 255:19AM. Do you know what your validation criteria are?](https://hdevalence.ca/blog/2020-10-04-its-25519am)
57 |
--------------------------------------------------------------------------------
/spec/p2p/messages/block-sync.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 2
3 | ---
4 |
5 | # Block Sync
6 |
7 | ## Channel
8 |
9 | Block sync has one channel.
10 |
11 | | Name | Number |
12 | |-------------------|--------|
13 | | BlockchainChannel | 64 |
14 |
15 | ## Message Types
16 |
17 | There are multiple message types for Block Sync
18 |
19 | ### BlockRequest
20 |
21 | BlockRequest asks a peer for a block at the height specified.
22 |
23 | | Name | Type | Description | Field Number |
24 | |--------|-------|---------------------------|--------------|
25 | | Height | int64 | Height of requested block | 1 |
26 |
27 | ### NoBlockResponse
28 |
29 | NoBlockResponse notifies the peer requesting a block that the node does not contain it.
30 |
31 | | Name | Type | Description | Field Number |
32 | |--------|-------|---------------------------|--------------|
33 | | Height | int64 | Height of requested block | 1 |
34 |
35 | ### BlockResponse
36 |
37 | BlockResponse contains the block requested.
38 |
39 | | Name | Type | Description | Field Number |
40 | |-------|----------------------------------------------|-----------------|--------------|
41 | | Block | [Block](../../core/data_structures.md#block) | Requested Block | 1 |
42 |
43 | ### StatusRequest
44 |
45 | StatusRequest is an empty message that notifies the peer to respond with the highest and lowest blocks it has stored.
46 |
47 | > Empty message.
48 |
49 | ### StatusResponse
50 |
51 | StatusResponse responds to a peer with the highest and lowest block stored.
52 |
53 | | Name | Type | Description | Field Number |
54 | |--------|-------|-------------------------------------------------------------------|--------------|
55 | | Height | int64 | Current Height of a node | 1 |
56 | | base | int64 | First known block, if pruning is enabled it will be higher than 1 | 1 |
57 |
58 | ### Message
59 |
60 | Message is a [`oneof` protobuf type](https://developers.google.com/protocol-buffers/docs/proto#oneof). The `oneof` consists of five messages.
61 |
62 | | Name | Type | Description | Field Number |
63 | |-------------------|----------------------------------|--------------------------------------------------------------|--------------|
64 | | block_request | [BlockRequest](#blockrequest) | Request a block from a peer | 1 |
65 | | no_block_response | [NoBlockResponse](#noblockresponse) | Response saying it doe snot have the requested block | 2 |
66 | | block_response | [BlockResponse](#blockresponse) | Response with requested block | 3 |
67 | | status_request | [StatusRequest](#statusrequest) | Request the highest and lowest block numbers from a peer | 4 |
68 | | status_response | [StatusResponse](#statusresponse) | Response with the highest and lowest block numbers the store | 5 |
69 |
--------------------------------------------------------------------------------
/spec/consensus/bft-time.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 2
3 | ---
4 | # BFT Time
5 |
6 | Tendermint provides a deterministic, Byzantine fault-tolerant, source of time.
7 | Time in Tendermint is defined with the Time field of the block header.
8 |
9 | It satisfies the following properties:
10 |
11 | - Time Monotonicity: Time is monotonically increasing, i.e., given
12 | a header H1 for height h1 and a header H2 for height `h2 = h1 + 1`, `H1.Time < H2.Time`.
13 | - Time Validity: Given a set of Commit votes that forms the `block.LastCommit` field, a range of
14 | valid values for the Time field of the block header is defined only by
15 | Precommit messages (from the LastCommit field) sent by correct processes, i.e.,
16 | a faulty process cannot arbitrarily increase the Time value.
17 |
18 | In the context of Tendermint, time is of type int64 and denotes UNIX time in milliseconds, i.e.,
19 | corresponds to the number of milliseconds since January 1, 1970. Before defining rules that need to be enforced by the
20 | Tendermint consensus protocol, so the properties above holds, we introduce the following definition:
21 |
22 | - median of a Commit is equal to the median of `Vote.Time` fields of the `Vote` messages,
23 | where the value of `Vote.Time` is counted number of times proportional to the process voting power. As in Tendermint
24 | the voting power is not uniform (one process one vote), a vote message is actually an aggregator of the same votes whose
25 | number is equal to the voting power of the process that has casted the corresponding votes message.
26 |
27 | Let's consider the following example:
28 |
29 | - we have four processes p1, p2, p3 and p4, with the following voting power distribution (p1, 23), (p2, 27), (p3, 10)
30 | and (p4, 10). The total voting power is 70 (`N = 3f+1`, where `N` is the total voting power, and `f` is the maximum voting
31 | power of the faulty processes), so we assume that the faulty processes have at most 23 of voting power.
32 | Furthermore, we have the following vote messages in some LastCommit field (we ignore all fields except Time field):
33 | - (p1, 100), (p2, 98), (p3, 1000), (p4, 500). We assume that p3 and p4 are faulty processes. Let's assume that the
34 | `block.LastCommit` message contains votes of processes p2, p3 and p4. Median is then chosen the following way:
35 | the value 98 is counted 27 times, the value 1000 is counted 10 times and the value 500 is counted also 10 times.
36 | So the median value will be the value 98. No matter what set of messages with at least `2f+1` voting power we
37 | choose, the median value will always be between the values sent by correct processes.
38 |
39 | We ensure Time Monotonicity and Time Validity properties by the following rules:
40 |
41 | - let rs denotes `RoundState` (consensus internal state) of some process. Then
42 | `rs.ProposalBlock.Header.Time == median(rs.LastCommit) &&
43 | rs.Proposal.Timestamp == rs.ProposalBlock.Header.Time`.
44 |
45 | - Furthermore, when creating the `vote` message, the following rules for determining `vote.Time` field should hold:
46 |
47 | - if `rs.LockedBlock` is defined then
48 | `vote.Time = max(rs.LockedBlock.Timestamp + time.Millisecond, time.Now())`, where `time.Now()`
49 | denotes local Unix time in milliseconds
50 |
51 | - else if `rs.Proposal` is defined then
52 | `vote.Time = max(rs.Proposal.Timestamp + time.Millisecond,, time.Now())`,
53 |
54 | - otherwise, `vote.Time = time.Now())`. In this case vote is for `nil` so it is not taken into account for
55 | the timestamp of the next block.
56 |
--------------------------------------------------------------------------------
/spec/light-client/verification/003bmc-apalache-error.csv:
--------------------------------------------------------------------------------
1 | no;filename;tool;timeout;init;inv;next;args
2 | 1;MC4_3_correct.tla;apalache;1h;;StoredHeadersAreVerifiedInv;;--length=5
3 | 2;MC4_3_correct.tla;apalache;1h;;PositiveBeforeTrustedHeaderExpires;;--length=5
4 | 3;MC4_3_correct.tla;apalache;1h;;CorrectPrimaryAndTimeliness;;--length=5
5 | 4;MC4_3_correct.tla;apalache;1h;;PrecisionInv;;--length=5
6 | 5;MC4_3_correct.tla;apalache;1h;;PrecisionBuggyInv;;--length=5
7 | 6;MC4_3_correct.tla;apalache;1h;;SuccessOnCorrectPrimaryAndChainOfTrustGlobal;;--length=5
8 | 7;MC4_3_correct.tla;apalache;1h;;SuccessOnCorrectPrimaryAndChainOfTrustLocal;;--length=5
9 | 8;MC4_4_correct.tla;apalache;1h;;StoredHeadersAreVerifiedInv;;--length=7
10 | 9;MC4_4_correct.tla;apalache;1h;;PositiveBeforeTrustedHeaderExpires;;--length=7
11 | 10;MC4_4_correct.tla;apalache;1h;;CorrectPrimaryAndTimeliness;;--length=7
12 | 11;MC4_4_correct.tla;apalache;1h;;PrecisionInv;;--length=7
13 | 12;MC4_4_correct.tla;apalache;1h;;PrecisionBuggyInv;;--length=7
14 | 13;MC4_4_correct.tla;apalache;1h;;SuccessOnCorrectPrimaryAndChainOfTrustGlobal;;--length=7
15 | 14;MC4_4_correct.tla;apalache;1h;;SuccessOnCorrectPrimaryAndChainOfTrustLocal;;--length=7
16 | 15;MC4_5_correct.tla;apalache;1h;;StoredHeadersAreVerifiedInv;;--length=11
17 | 16;MC4_5_correct.tla;apalache;1h;;PositiveBeforeTrustedHeaderExpires;;--length=11
18 | 17;MC4_5_correct.tla;apalache;1h;;CorrectPrimaryAndTimeliness;;--length=11
19 | 18;MC4_5_correct.tla;apalache;1h;;PrecisionInv;;--length=11
20 | 19;MC4_5_correct.tla;apalache;1h;;PrecisionBuggyInv;;--length=11
21 | 20;MC4_5_correct.tla;apalache;1h;;SuccessOnCorrectPrimaryAndChainOfTrustGlobal;;--length=11
22 | 21;MC4_5_correct.tla;apalache;1h;;SuccessOnCorrectPrimaryAndChainOfTrustLocal;;--length=11
23 | 22;MC4_5_correct.tla;apalache;1h;;StoredHeadersAreVerifiedOrNotTrustedInv;;--length=11
24 | 23;MC4_3_faulty.tla;apalache;1h;;StoredHeadersAreVerifiedInv;;--length=5
25 | 24;MC4_3_faulty.tla;apalache;1h;;PositiveBeforeTrustedHeaderExpires;;--length=5
26 | 25;MC4_3_faulty.tla;apalache;1h;;CorrectPrimaryAndTimeliness;;--length=5
27 | 26;MC4_3_faulty.tla;apalache;1h;;PrecisionInv;;--length=5
28 | 27;MC4_3_faulty.tla;apalache;1h;;PrecisionBuggyInv;;--length=5
29 | 28;MC4_3_faulty.tla;apalache;1h;;SuccessOnCorrectPrimaryAndChainOfTrustGlobal;;--length=5
30 | 29;MC4_3_faulty.tla;apalache;1h;;SuccessOnCorrectPrimaryAndChainOfTrustLocal;;--length=5
31 | 30;MC4_4_faulty.tla;apalache;1h;;StoredHeadersAreVerifiedInv;;--length=7
32 | 31;MC4_4_faulty.tla;apalache;1h;;PositiveBeforeTrustedHeaderExpires;;--length=7
33 | 32;MC4_4_faulty.tla;apalache;1h;;CorrectPrimaryAndTimeliness;;--length=7
34 | 33;MC4_4_faulty.tla;apalache;1h;;PrecisionInv;;--length=7
35 | 34;MC4_4_faulty.tla;apalache;1h;;PrecisionBuggyInv;;--length=7
36 | 35;MC4_4_faulty.tla;apalache;1h;;SuccessOnCorrectPrimaryAndChainOfTrustGlobal;;--length=7
37 | 36;MC4_4_faulty.tla;apalache;1h;;SuccessOnCorrectPrimaryAndChainOfTrustLocal;;--length=7
38 | 37;MC4_5_faulty.tla;apalache;1h;;StoredHeadersAreVerifiedInv;;--length=11
39 | 38;MC4_5_faulty.tla;apalache;1h;;PositiveBeforeTrustedHeaderExpires;;--length=11
40 | 39;MC4_5_faulty.tla;apalache;1h;;CorrectPrimaryAndTimeliness;;--length=11
41 | 40;MC4_5_faulty.tla;apalache;1h;;PrecisionInv;;--length=11
42 | 41;MC4_5_faulty.tla;apalache;1h;;PrecisionBuggyInv;;--length=11
43 | 42;MC4_5_faulty.tla;apalache;1h;;SuccessOnCorrectPrimaryAndChainOfTrustGlobal;;--length=11
44 | 43;MC4_5_faulty.tla;apalache;1h;;SuccessOnCorrectPrimaryAndChainOfTrustLocal;;--length=11
45 | 44;MC4_5_faulty.tla;apalache;1h;;StoredHeadersAreVerifiedOrNotTrustedInv;;--length=11
46 |
--------------------------------------------------------------------------------
/spec/light-client/verification/001bmc-apalache.csv:
--------------------------------------------------------------------------------
1 | no,filename,tool,timeout,init,inv,next,args
2 | 1,MC4_3_correct.tla,apalache,1h,,PositiveBeforeTrustedHeaderExpires,,--length=30
3 | 2,MC4_3_correct.tla,apalache,1h,,CorrectnessInv,,--length=30
4 | 3,MC4_3_correct.tla,apalache,1h,,PrecisionInv,,--length=30
5 | 4,MC4_3_correct.tla,apalache,1h,,SuccessOnCorrectPrimaryAndChainOfTrust,,--length=30
6 | 5,MC4_3_correct.tla,apalache,1h,,NoFailedBlocksOnSuccessInv,,--length=30
7 | 6,MC4_3_correct.tla,apalache,1h,,StoredHeadersAreVerifiedOrNotTrustedInv,,--length=30
8 | 7,MC4_3_correct.tla,apalache,1h,,CorrectPrimaryAndTimeliness,,--length=30
9 | 8,MC4_3_correct.tla,apalache,1h,,Complexity,,--length=30
10 | 9,MC4_3_faulty.tla,apalache,1h,,PositiveBeforeTrustedHeaderExpires,,--length=30
11 | 10,MC4_3_faulty.tla,apalache,1h,,CorrectnessInv,,--length=30
12 | 11,MC4_3_faulty.tla,apalache,1h,,PrecisionInv,,--length=30
13 | 12,MC4_3_faulty.tla,apalache,1h,,SuccessOnCorrectPrimaryAndChainOfTrust,,--length=30
14 | 13,MC4_3_faulty.tla,apalache,1h,,NoFailedBlocksOnSuccessInv,,--length=30
15 | 14,MC4_3_faulty.tla,apalache,1h,,StoredHeadersAreVerifiedOrNotTrustedInv,,--length=30
16 | 15,MC4_3_faulty.tla,apalache,1h,,CorrectPrimaryAndTimeliness,,--length=30
17 | 16,MC4_3_faulty.tla,apalache,1h,,Complexity,,--length=30
18 | 17,MC5_5_correct.tla,apalache,1h,,PositiveBeforeTrustedHeaderExpires,,--length=30
19 | 18,MC5_5_correct.tla,apalache,1h,,CorrectnessInv,,--length=30
20 | 19,MC5_5_correct.tla,apalache,1h,,PrecisionInv,,--length=30
21 | 20,MC5_5_correct.tla,apalache,1h,,SuccessOnCorrectPrimaryAndChainOfTrust,,--length=30
22 | 21,MC5_5_correct.tla,apalache,1h,,NoFailedBlocksOnSuccessInv,,--length=30
23 | 22,MC5_5_correct.tla,apalache,1h,,StoredHeadersAreVerifiedOrNotTrustedInv,,--length=30
24 | 23,MC5_5_correct.tla,apalache,1h,,CorrectPrimaryAndTimeliness,,--length=30
25 | 24,MC5_5_correct.tla,apalache,1h,,Complexity,,--length=30
26 | 25,MC5_5_faulty.tla,apalache,1h,,PositiveBeforeTrustedHeaderExpires,,--length=30
27 | 26,MC5_5_faulty.tla,apalache,1h,,CorrectnessInv,,--length=30
28 | 27,MC5_5_faulty.tla,apalache,1h,,PrecisionInv,,--length=30
29 | 28,MC5_5_faulty.tla,apalache,1h,,SuccessOnCorrectPrimaryAndChainOfTrust,,--length=30
30 | 29,MC5_5_faulty.tla,apalache,1h,,NoFailedBlocksOnSuccessInv,,--length=30
31 | 30,MC5_5_faulty.tla,apalache,1h,,StoredHeadersAreVerifiedOrNotTrustedInv,,--length=30
32 | 31,MC5_5_faulty.tla,apalache,1h,,CorrectPrimaryAndTimeliness,,--length=30
33 | 32,MC5_5_faulty.tla,apalache,1h,,Complexity,,--length=30
34 | 33,MC7_5_faulty.tla,apalache,10h,,PositiveBeforeTrustedHeaderExpires,,--length=30
35 | 34,MC7_5_faulty.tla,apalache,10h,,CorrectnessInv,,--length=30
36 | 35,MC7_5_faulty.tla,apalache,10h,,PrecisionInv,,--length=30
37 | 36,MC7_5_faulty.tla,apalache,10h,,SuccessOnCorrectPrimaryAndChainOfTrust,,--length=30
38 | 37,MC7_5_faulty.tla,apalache,10h,,NoFailedBlocksOnSuccessInv,,--length=30
39 | 38,MC7_5_faulty.tla,apalache,10h,,StoredHeadersAreVerifiedOrNotTrustedInv,,--length=30
40 | 39,MC7_5_faulty.tla,apalache,10h,,CorrectPrimaryAndTimeliness,,--length=30
41 | 40,MC7_5_faulty.tla,apalache,10h,,Complexity,,--length=30
42 | 41,MC4_7_faulty.tla,apalache,10h,,PositiveBeforeTrustedHeaderExpires,,--length=30
43 | 42,MC4_7_faulty.tla,apalache,10h,,CorrectnessInv,,--length=30
44 | 43,MC4_7_faulty.tla,apalache,10h,,PrecisionInv,,--length=30
45 | 44,MC4_7_faulty.tla,apalache,10h,,SuccessOnCorrectPrimaryAndChainOfTrust,,--length=30
46 | 45,MC4_7_faulty.tla,apalache,10h,,NoFailedBlocksOnSuccessInv,,--length=30
47 | 46,MC4_7_faulty.tla,apalache,10h,,StoredHeadersAreVerifiedOrNotTrustedInv,,--length=30
48 | 47,MC4_7_faulty.tla,apalache,10h,,CorrectPrimaryAndTimeliness,,--length=30
49 | 48,MC4_7_faulty.tla,apalache,10h,,Complexity,,--length=30
50 |
--------------------------------------------------------------------------------
/rfc/002-nonzero-genesis.md:
--------------------------------------------------------------------------------
1 | # RFC 002: Non-Zero Genesis
2 |
3 | ## Changelog
4 |
5 | - 2020-07-26: Initial draft (@erikgrinaker)
6 | - 2020-07-28: Use weak chain linking, i.e. `predecessor` field (@erikgrinaker)
7 | - 2020-07-31: Drop chain linking (@erikgrinaker)
8 | - 2020-08-03: Add `State.InitialHeight` (@erikgrinaker)
9 |
10 | ## Author(s)
11 |
12 | - Erik Grinaker (@erikgrinaker)
13 |
14 | ## Context
15 |
16 | The recommended upgrade path for block protocol-breaking upgrades is currently to hard fork the
17 | chain (see e.g. [`cosmoshub-3` upgrade](https://blog.cosmos.network/cosmos-hub-3-upgrade-announcement-39c9da941aee)).
18 | This is done by halting all validators at a predetermined height, exporting the application
19 | state via application-specific tooling, and creating an entirely new chain using the exported
20 | application state.
21 |
22 | As far as Tendermint is concerned, the upgraded chain is a completely separate chain, with e.g.
23 | a new chain ID and genesis file. Notably, the new chain starts at height 1, and has none of the
24 | old chain's block history. This causes problems for integrators, e.g. coin exchanges and
25 | wallets, that assume a monotonically increasing height for a given blockchain. Users also find
26 | it confusing that a given height can now refer to distinct states depending on the chain
27 | version.
28 |
29 | An ideal solution would be to always retain block backwards compatibility in such a way that chain
30 | history is never lost on upgrades. However, this may require a significant amount of engineering
31 | work that is not viable for the planned Stargate release (Tendermint 0.34), and may prove too
32 | restrictive for future development.
33 |
34 | As a first step, allowing the new chain to start from an initial height specified in the genesis
35 | file would at least provide monotonically increasing heights. There was a proposal to include the
36 | last block header of the previous chain as well, but since the genesis file is not verified and
37 | hashed (only specific fields are) this would not be trustworthy.
38 |
39 | External tooling will be required to map historical heights onto e.g. archive nodes that contain
40 | blocks from previous chain version. Tendermint will not include any such functionality.
41 |
42 | ## Proposal
43 |
44 | Tendermint will allow chains to start from an arbitrary initial height:
45 |
46 | - A new field `initial_height` is added to the genesis file, defaulting to `1`. It can be set to any
47 | non-negative integer, and `0` is considered equivalent to `1`.
48 |
49 | - A new field `InitialHeight` is added to the ABCI `RequestInitChain` message, with the same value
50 | and semantics as the genesis field.
51 |
52 | - A new field `InitialHeight` is added to the `state.State` struct, where `0` is considered invalid.
53 | Including the field here simplifies implementation, since the genesis value does not have to be
54 | propagated throughout the code base separately, but it is not strictly necessary.
55 |
56 | ABCI applications may have to be updated to handle arbitrary initial heights, otherwise the initial
57 | block may fail.
58 |
59 | ## Status
60 |
61 | Accepted
62 |
63 | ## Consequences
64 |
65 | ### Positive
66 |
67 | - Heights can be unique throughout the history of a "logical" chain, across hard fork upgrades.
68 |
69 | ### Negative
70 |
71 | - Upgrades still cause loss of block history.
72 |
73 | - Integrators will have to map height ranges to specific archive nodes/networks to query history.
74 |
75 | ### Neutral
76 |
77 | - There is no explicit link to the last block of the previous chain.
78 |
79 | ## References
80 |
81 | - [#2543: Allow genesis file to start from non-zero height w/ prev block header](https://github.com/tendermint/tendermint/issues/2543)
82 |
--------------------------------------------------------------------------------
/proto/tendermint/consensus/types.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package tendermint.consensus;
3 |
4 | import "gogoproto/gogo.proto";
5 | import "tendermint/types/types.proto";
6 | import "tendermint/libs/bits/types.proto";
7 |
8 | // NewRoundStep is sent for every step taken in the ConsensusState.
9 | // For every height/round/step transition
10 | message NewRoundStep {
11 | int64 height = 1;
12 | int32 round = 2;
13 | uint32 step = 3;
14 | int64 seconds_since_start_time = 4;
15 | int32 last_commit_round = 5;
16 | }
17 |
18 | // NewValidBlock is sent when a validator observes a valid block B in some round
19 | // r,
20 | // i.e., there is a Proposal for block B and 2/3+ prevotes for the block B in
21 | // the round r.
22 | // In case the block is also committed, then IsCommit flag is set to true.
23 | message NewValidBlock {
24 | int64 height = 1;
25 | int32 round = 2;
26 | tendermint.types.PartSetHeader block_part_set_header = 3
27 | [(gogoproto.nullable) = false];
28 | tendermint.libs.bits.BitArray block_parts = 4;
29 | bool is_commit = 5;
30 | }
31 |
32 | // Proposal is sent when a new block is proposed.
33 | message Proposal {
34 | tendermint.types.Proposal proposal = 1 [(gogoproto.nullable) = false];
35 | }
36 |
37 | // ProposalPOL is sent when a previous proposal is re-proposed.
38 | message ProposalPOL {
39 | int64 height = 1;
40 | int32 proposal_pol_round = 2;
41 | tendermint.libs.bits.BitArray proposal_pol = 3
42 | [(gogoproto.nullable) = false];
43 | }
44 |
45 | // BlockPart is sent when gossipping a piece of the proposed block.
46 | message BlockPart {
47 | int64 height = 1;
48 | int32 round = 2;
49 | tendermint.types.Part part = 3 [(gogoproto.nullable) = false];
50 | }
51 |
52 | // Vote is sent when voting for a proposal (or lack thereof).
53 | message Vote {
54 | tendermint.types.Vote vote = 1;
55 | }
56 |
57 | // HasVote is sent to indicate that a particular vote has been received.
58 | message HasVote {
59 | int64 height = 1;
60 | int32 round = 2;
61 | tendermint.types.SignedMsgType type = 3;
62 | int32 index = 4;
63 | }
64 |
65 | // VoteSetMaj23 is sent to indicate that a given BlockID has seen +2/3 votes.
66 | message VoteSetMaj23 {
67 | int64 height = 1;
68 | int32 round = 2;
69 | tendermint.types.SignedMsgType type = 3;
70 | tendermint.types.BlockID block_id = 4
71 | [(gogoproto.customname) = "BlockID", (gogoproto.nullable) = false];
72 | }
73 |
74 | // VoteSetBits is sent to communicate the bit-array of votes seen for the
75 | // BlockID.
76 | message VoteSetBits {
77 | int64 height = 1;
78 | int32 round = 2;
79 | tendermint.types.SignedMsgType type = 3;
80 | tendermint.types.BlockID block_id = 4
81 | [(gogoproto.customname) = "BlockID", (gogoproto.nullable) = false];
82 | tendermint.libs.bits.BitArray votes = 5 [(gogoproto.nullable) = false];
83 | }
84 |
85 | message Message {
86 | oneof sum {
87 | NewRoundStep new_round_step = 1;
88 | NewValidBlock new_valid_block = 2;
89 | Proposal proposal = 3;
90 | ProposalPOL proposal_pol = 4;
91 | BlockPart block_part = 5;
92 | Vote vote = 6;
93 | HasVote has_vote = 7;
94 | VoteSetMaj23 vote_set_maj23 = 8;
95 | VoteSetBits vote_set_bits = 9;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/spec/light-client/verification/002bmc-apalache-ok.csv:
--------------------------------------------------------------------------------
1 | no;filename;tool;timeout;init;inv;next;args
2 | 1;MC4_3_correct.tla;apalache;1h;;TargetHeightOnSuccessInv;;--length=5
3 | 2;MC4_3_correct.tla;apalache;1h;;StoredHeadersAreVerifiedOrNotTrustedInv;;--length=5
4 | 3;MC4_3_correct.tla;apalache;1h;;CorrectnessInv;;--length=5
5 | 4;MC4_3_correct.tla;apalache;1h;;NoTrustOnFaultyBlockInv;;--length=5
6 | 5;MC4_3_correct.tla;apalache;1h;;ProofOfChainOfTrustInv;;--length=5
7 | 6;MC4_3_correct.tla;apalache;1h;;NoFailedBlocksOnSuccessInv;;--length=5
8 | 7;MC4_3_correct.tla;apalache;1h;;Complexity;;--length=5
9 | 8;MC4_3_correct.tla;apalache;1h;;ApiPostInv;;--length=5
10 | 9;MC4_4_correct.tla;apalache;1h;;TargetHeightOnSuccessInv;;--length=7
11 | 10;MC4_4_correct.tla;apalache;1h;;CorrectnessInv;;--length=7
12 | 11;MC4_4_correct.tla;apalache;1h;;NoTrustOnFaultyBlockInv;;--length=7
13 | 12;MC4_4_correct.tla;apalache;1h;;ProofOfChainOfTrustInv;;--length=7
14 | 13;MC4_4_correct.tla;apalache;1h;;NoFailedBlocksOnSuccessInv;;--length=7
15 | 14;MC4_4_correct.tla;apalache;1h;;Complexity;;--length=7
16 | 15;MC4_4_correct.tla;apalache;1h;;ApiPostInv;;--length=7
17 | 16;MC4_5_correct.tla;apalache;1h;;TargetHeightOnSuccessInv;;--length=11
18 | 17;MC4_5_correct.tla;apalache;1h;;CorrectnessInv;;--length=11
19 | 18;MC4_5_correct.tla;apalache;1h;;NoTrustOnFaultyBlockInv;;--length=11
20 | 19;MC4_5_correct.tla;apalache;1h;;ProofOfChainOfTrustInv;;--length=11
21 | 20;MC4_5_correct.tla;apalache;1h;;NoFailedBlocksOnSuccessInv;;--length=11
22 | 21;MC4_5_correct.tla;apalache;1h;;Complexity;;--length=11
23 | 22;MC4_5_correct.tla;apalache;1h;;ApiPostInv;;--length=11
24 | 23;MC5_5_correct.tla;apalache;1h;;TargetHeightOnSuccessInv;;--length=11
25 | 24;MC5_5_correct.tla;apalache;1h;;CorrectnessInv;;--length=11
26 | 25;MC5_5_correct.tla;apalache;1h;;NoTrustOnFaultyBlockInv;;--length=11
27 | 26;MC5_5_correct.tla;apalache;1h;;ProofOfChainOfTrustInv;;--length=11
28 | 27;MC5_5_correct.tla;apalache;1h;;NoFailedBlocksOnSuccessInv;;--length=11
29 | 28;MC5_5_correct.tla;apalache;1h;;Complexity;;--length=11
30 | 29;MC5_5_correct.tla;apalache;1h;;ApiPostInv;;--length=11
31 | 30;MC4_3_faulty.tla;apalache;1h;;TargetHeightOnSuccessInv;;--length=5
32 | 31;MC4_3_faulty.tla;apalache;1h;;StoredHeadersAreVerifiedOrNotTrustedInv;;--length=5
33 | 32;MC4_3_faulty.tla;apalache;1h;;CorrectnessInv;;--length=5
34 | 33;MC4_3_faulty.tla;apalache;1h;;NoTrustOnFaultyBlockInv;;--length=5
35 | 34;MC4_3_faulty.tla;apalache;1h;;ProofOfChainOfTrustInv;;--length=5
36 | 35;MC4_3_faulty.tla;apalache;1h;;NoFailedBlocksOnSuccessInv;;--length=5
37 | 36;MC4_3_faulty.tla;apalache;1h;;Complexity;;--length=5
38 | 37;MC4_3_faulty.tla;apalache;1h;;ApiPostInv;;--length=5
39 | 38;MC4_4_faulty.tla;apalache;1h;;TargetHeightOnSuccessInv;;--length=7
40 | 39;MC4_4_faulty.tla;apalache;1h;;StoredHeadersAreVerifiedOrNotTrustedInv;;--length=7
41 | 40;MC4_4_faulty.tla;apalache;1h;;CorrectnessInv;;--length=7
42 | 41;MC4_4_faulty.tla;apalache;1h;;NoTrustOnFaultyBlockInv;;--length=7
43 | 42;MC4_4_faulty.tla;apalache;1h;;ProofOfChainOfTrustInv;;--length=7
44 | 43;MC4_4_faulty.tla;apalache;1h;;NoFailedBlocksOnSuccessInv;;--length=7
45 | 44;MC4_4_faulty.tla;apalache;1h;;Complexity;;--length=7
46 | 45;MC4_4_faulty.tla;apalache;1h;;ApiPostInv;;--length=7
47 | 46;MC4_5_faulty.tla;apalache;1h;;TargetHeightOnSuccessInv;;--length=11
48 | 47;MC4_5_faulty.tla;apalache;1h;;StoredHeadersAreVerifiedOrNotTrustedInv;;--length=11
49 | 48;MC4_5_faulty.tla;apalache;1h;;CorrectnessInv;;--length=11
50 | 49;MC4_5_faulty.tla;apalache;1h;;NoTrustOnFaultyBlockInv;;--length=11
51 | 50;MC4_5_faulty.tla;apalache;1h;;ProofOfChainOfTrustInv;;--length=11
52 | 51;MC4_5_faulty.tla;apalache;1h;;NoFailedBlocksOnSuccessInv;;--length=11
53 | 52;MC4_5_faulty.tla;apalache;1h;;Complexity;;--length=11
54 | 53;MC4_5_faulty.tla;apalache;1h;;ApiPostInv;;--length=11
55 |
56 |
--------------------------------------------------------------------------------
/spec/p2p/node.md:
--------------------------------------------------------------------------------
1 | **THIS REPOSITORY HAS BEEN ARCHIVED. THE TENDERMINT SPECIFICATION IS NOW LOCATED IN THE [TENDERMINT/TENDERMINT](https://github.com/tendermint/tendermint/tree/master/spec) REPOSITORY.**
2 |
3 | ---
4 |
5 | # Peer Discovery
6 |
7 | A Tendermint P2P network has different kinds of nodes with different requirements for connectivity to one another.
8 | This document describes what kind of nodes Tendermint should enable and how they should work.
9 |
10 | ## Seeds
11 |
12 | Seeds are the first point of contact for a new node.
13 | They return a list of known active peers and then disconnect.
14 |
15 | Seeds should operate full nodes with the PEX reactor in a "crawler" mode
16 | that continuously explores to validate the availability of peers.
17 |
18 | Seeds should only respond with some top percentile of the best peers it knows about.
19 |
20 | ## New Full Node
21 |
22 | A new node needs a few things to connect to the network:
23 |
24 | - a list of seeds, which can be provided to Tendermint via config file or flags,
25 | or hardcoded into the software by in-process apps
26 | - a `ChainID`, also called `Network` at the p2p layer
27 | - a recent block height, H, and hash, HASH for the blockchain.
28 |
29 | The values `H` and `HASH` must be received and corroborated by means external to Tendermint, and specific to the user - ie. via the user's trusted social consensus.
30 | This requirement to validate `H` and `HASH` out-of-band and via social consensus
31 | is the essential difference in security models between Proof-of-Work and Proof-of-Stake blockchains.
32 |
33 | With the above, the node then queries some seeds for peers for its chain,
34 | dials those peers, and runs the Tendermint protocols with those it successfully connects to.
35 |
36 | When the peer catches up to height H, it ensures the block hash matches HASH.
37 | If not, Tendermint will exit, and the user must try again - either they are connected
38 | to bad peers or their social consensus is invalid.
39 |
40 | ## Restarted Full Node
41 |
42 | A node checks its address book on startup and attempts to connect to peers from there.
43 | If it can't connect to any peers after some time, it falls back to the seeds to find more.
44 |
45 | Restarted full nodes can run the `blockchain` or `consensus` reactor protocols to sync up
46 | to the latest state of the blockchain from wherever they were last.
47 | In a Proof-of-Stake context, if they are sufficiently far behind (greater than the length
48 | of the unbonding period), they will need to validate a recent `H` and `HASH` out-of-band again
49 | so they know they have synced the correct chain.
50 |
51 | ## Validator Node
52 |
53 | A validator node is a node that interfaces with a validator signing key.
54 | These nodes require the highest security, and should not accept incoming connections.
55 | They should maintain outgoing connections to a controlled set of "Sentry Nodes" that serve
56 | as their proxy shield to the rest of the network.
57 |
58 | Validators that know and trust each other can accept incoming connections from one another and maintain direct private connectivity via VPN.
59 |
60 | ## Sentry Node
61 |
62 | Sentry nodes are guardians of a validator node and provide it access to the rest of the network.
63 | They should be well connected to other full nodes on the network.
64 | Sentry nodes may be dynamic, but should maintain persistent connections to some evolving random subset of each other.
65 | They should always expect to have direct incoming connections from the validator node and its backup(s).
66 | They do not report the validator node's address in the PEX and
67 | they may be more strict about the quality of peers they keep.
68 |
69 | Sentry nodes belonging to validators that trust each other may wish to maintain persistent connections via VPN with one another, but only report each other sparingly in the PEX.
70 |
--------------------------------------------------------------------------------
/ivy-proofs/classic_safety.ivy:
--------------------------------------------------------------------------------
1 | #lang ivy1.7
2 | # ---
3 | # layout: page
4 | # title: Proof of Classic Safety
5 | # ---
6 |
7 | include tendermint
8 | include abstract_tendermint
9 |
10 | # Here we prove the classic safety property: assuming that every two quorums
11 | # have a well-behaved node in common, no two well-behaved nodes ever disagree.
12 |
13 | # The proof is done in two steps: first we prove the the abstract specification
14 | # satisfies the property, and then we show by refinement that this property
15 | # also holds in the concrete specification.
16 |
17 | # To see what is checked in the refinement proof, use `ivy_show isolate=classic_safety classic_safety.ivy`
18 | # To see what is checked in the abstract correctness proof, use `ivy_show isolate=abstract_classic_safety classic_safety.ivy`
19 |
20 | # To check the whole proof, use `ivy_check classic_safety.ivy`.
21 |
22 | # Note that all the verification conditions sent to Z3 for this proof are in
23 | # EPR.
24 |
25 | # Classic safety in the abstract model
26 | # ====================================
27 |
28 | # We start by proving that classic safety holds in the abstract model.
29 |
30 | isolate abstract_classic_safety = {
31 |
32 | instantiate abstract_tendermint
33 |
34 | invariant [classic_safety] classic_bft.quorum_intersection & decided(N1,R1,V1) & decided(N2,R2,V2) -> V1 = V2
35 |
36 | # The notion of choosable value
37 | # -----------------------------
38 |
39 | relation choosable(R:round, V:value)
40 | definition choosable(R,V) = exists Q . nset.is_quorum(Q) & forall N . well_behaved(N) & nset.member(N,Q) -> ~left_round(N,R) | precommitted(N,R,V)
41 |
42 | # Main invariants
43 | # ---------------
44 |
45 | # `classic_safety` is inductive relative to those invariants
46 |
47 | invariant [decision_is_quorum_precommit] (exists N1 . decided(N1,R,V)) -> exists Q. nset.is_quorum(Q) & forall N2. well_behaved(N2) & nset.member(N2, Q) -> precommitted(N2,R,V)
48 |
49 | invariant [precommitted_is_quorum_prevote] V ~= value.nil & (exists N1 . precommitted(N1,R,V)) -> exists Q. nset.is_quorum(Q) & forall N2. well_behaved(N2) & nset.member(N2, Q) -> prevoted(N2,R,V)
50 |
51 | invariant [prevote_unique_per_round] prevoted(N,R,V1) & prevoted(N,R,V2) -> V1 = V2
52 |
53 | # This is the core invariant: as long as a precommitted value is still choosable, it remains protected by a lock and prevents any new value from being prevoted:
54 | invariant [locks] classic_bft.quorum_intersection & V ~= value.nil & precommitted(N,R,V) & choosable(R,V) -> locked(N,R,V) & forall R2,V2 . R < R2 & prevoted(N,R2,V2) -> V2 = V | V2 = value.nil
55 |
56 | # Supporting invariants
57 | # ---------------------
58 |
59 | # The main invariants are inductive relative to those
60 |
61 | invariant decided(N,R,V) -> V ~= value.nil
62 |
63 | invariant left_round(N,R2) & R1 < R2 -> left_round(N,R1) # if a node left round R2>R1, then it also left R1:
64 |
65 | invariant prevoted(N,R2,V2) & R1 < R2 -> left_round(N,R1)
66 | invariant precommitted(N,R2,V2) & R1 < R2 -> left_round(N,R1)
67 |
68 | } with round, nset, classic_bft.quorum_intersection_def
69 |
70 | # The refinement proof
71 | # ====================
72 |
73 | # Now, thanks to the refinement relation that we establish in
74 | # `concrete_tendermint.ivy`, we prove that classic safety transfers to the
75 | # concrete specification:
76 | isolate classic_safety = {
77 |
78 | # We instantiate the `tendermint` module providing `abstract_classic_safety` as abstract model.
79 | instantiate tendermint(abstract_classic_safety)
80 |
81 | # We prove that if every two quorums have a well-behaved node in common,
82 | # then well-behaved nodes never disagree:
83 | invariant [classic_safety] classic_bft.quorum_intersection & server.decision(N1) ~= value.nil & server.decision(N2) ~= value.nil -> server.decision(N1) = server.decision(N2)
84 |
85 | } with value, round, proposers, shim, abstract_classic_safety # here we list all the specifications that we rely on for this proof
86 |
--------------------------------------------------------------------------------
/spec/consensus/consensus-paper/technote.sty:
--------------------------------------------------------------------------------
1 | \NeedsTeXFormat{LaTeX2e}
2 | \ProvidesPackage{technote}[2007/11/09]
3 | \typeout{Template for quick notes with some useful definitions}
4 |
5 | \RequirePackage{ifthen}
6 | \RequirePackage{calc}
7 | \RequirePackage{amsmath,amssymb,amsthm}
8 | \RequirePackage{epsfig}
9 | \RequirePackage{algorithm}
10 | \RequirePackage[noend]{algorithmicplus}
11 |
12 | \newboolean{technote@noedit}
13 | \setboolean{technote@noedit}{false}
14 | \DeclareOption{noedit}{\setboolean{technote@noedit}{true}}
15 |
16 | \newcounter{technote@lang}
17 | \setcounter{technote@lang}{0}
18 | \DeclareOption{german}{\setcounter{technote@lang}{1}}
19 | \DeclareOption{french}{\setcounter{technote@lang}{2}}
20 |
21 | \DeclareOption{fullpage}{
22 | \oddsidemargin -10mm % Margin on odd side pages (default=0mm)
23 | \evensidemargin -10mm % Margin on even side pages (default=0mm)
24 | \topmargin -10mm % Top margin space (default=16mm)
25 | \headheight \baselineskip % Height of headers (default=0mm)
26 | \headsep \baselineskip % Separation spc btw header and text (d=0mm)
27 | \footskip 30pt % Separation spc btw text and footer (d=30pt)
28 | \textheight 230mm % Total text height (default=200mm)
29 | \textwidth 180mm % Total text width (default=160mm)
30 | }
31 |
32 | \renewcommand{\algorithmiccomment}[1]{\hfill/* #1 */}
33 | \renewcommand{\algorithmiclnosize}{\scriptsize}
34 |
35 | \newboolean{technote@truenumbers}
36 | \setboolean{technote@truenumbers}{false}
37 | \DeclareOption{truenumbers}{\setboolean{technote@truenumbers}{true}}
38 |
39 | \ProcessOptions
40 |
41 | \newcommand{\N}{\ifthenelse{\boolean{technote@truenumbers}}%
42 | {\mbox{\rm I\hspace{-.5em}N}}%
43 | {\mathbb{N}}}
44 |
45 | \newcommand{\R}{\ifthenelse{\boolean{technote@truenumbers}}%
46 | {\mbox{\rm I\hspace{-.2em}R}}%
47 | {\mathbb{R}}}
48 |
49 | \newcommand{\Z}{\mathbb{Z}}
50 |
51 | \newcommand{\set}[1]{\left\{#1\right\}}
52 | \newcommand{\mathsc}[1]{\mbox{\sc #1}}
53 | \newcommand{\li}[1]{\langle#1\rangle}
54 | \newcommand{\st}{\;s.t.\;}
55 | \newcommand{\Real}{\R}
56 | \newcommand{\Natural}{\N}
57 | \newcommand{\Integer}{\Z}
58 |
59 | % edit commands
60 | \newcommand{\newedit}[2]{
61 | \newcommand{#1}[2][default]{%
62 | \ifthenelse{\boolean{technote@noedit}}{}{
63 | \par\vspace{2mm}
64 | \noindent
65 | \begin{tabular}{|l|}\hline
66 | \parbox{\linewidth-\tabcolsep*2}{{\bf #2:}\hfill\ifthenelse{\equal{##1}{default}}{}{##1}}\\\hline
67 | \parbox{\linewidth-\tabcolsep*2}{\rule{0pt}{5mm}##2\rule[-2mm]{0pt}{2mm}}\\\hline
68 | \end{tabular}
69 | \par\vspace{2mm}
70 | }
71 | }
72 | }
73 |
74 | \newedit{\note}{Note}
75 | \newedit{\comment}{Comment}
76 | \newedit{\question}{Question}
77 | \newedit{\content}{Content}
78 | \newedit{\problem}{Problem}
79 |
80 | \newcommand{\mnote}[1]{\marginpar{\scriptsize\it
81 | \begin{minipage}[t]{0.8 in}
82 | \raggedright #1
83 | \end{minipage}}}
84 |
85 | \newcommand{\Insert}[1]{\underline{#1}\marginpar{$|$}}
86 |
87 | \newcommand{\Delete}[1]{\marginpar{$|$}
88 | }
89 |
90 | % lemma, theorem, etc.
91 | \newtheorem{lemma}{Lemma}
92 | \newtheorem{proposition}{Proposition}
93 | \newtheorem{theorem}{Theorem}
94 | \newtheorem{corollary}{Corollary}
95 | \newtheorem{assumption}{Assumption}
96 | \newtheorem{definition}{Definition}
97 |
98 | \gdef\op|{\,|\;}
99 | \gdef\op:{\,:\;}
100 | \newcommand{\assign}{\leftarrow}
101 | \newcommand{\inc}[1]{#1 \assign #1 + 1}
102 | \newcommand{\isdef}{:=}
103 |
104 | \newcommand{\ident}[1]{\mathit{#1}}
105 | \def\newident#1{\expandafter\def\csname #1\endcsname{\ident{#1}}}
106 |
107 | \newcommand{\eg}{{\it e.g.}}
108 | \newcommand{\ie}{{\it i.e.}}
109 | \newcommand{\apriori}{{\it apriori}}
110 | \newcommand{\etal}{{\it et al.}}
111 |
112 | \newcommand\ps@technote{%
113 | \renewcommand\@oddhead{\theheader}%
114 | \let\@evenhead\@oddhead
115 | \renewcommand\@evenfoot
116 | {\hfil\normalfont\textrm{\thepage}\hfil}%
117 | \let\@oddfoot\@evenfoot
118 | }
119 |
--------------------------------------------------------------------------------
/spec/light-client/accountability/Synopsis.md:
--------------------------------------------------------------------------------
1 |
2 | # Synopsis
3 |
4 | A TLA+ specification of a simplified Tendermint consensus, tuned for
5 | fork accountability. The simplifications are as follows:
6 |
7 | - the procotol runs for one height, that is, one-shot consensus
8 |
9 | - this specification focuses on safety, so timeouts are modelled with
10 | with non-determinism
11 |
12 | - the proposer function is non-determinstic, no fairness is assumed
13 |
14 | - the messages by the faulty processes are injected right in the initial states
15 |
16 | - every process has the voting power of 1
17 |
18 | - hashes are modelled as identity
19 |
20 | Having the above assumptions in mind, the specification follows the pseudo-code
21 | of the Tendermint paper:
22 |
23 | Byzantine processes can demonstrate arbitrary behavior, including
24 | no communication. However, we have to show that under the collective evidence
25 | collected by the correct processes, at least `f+1` Byzantine processes demonstrate
26 | one of the following behaviors:
27 |
28 | - Equivocation: a Byzantine process sends two different values
29 | in the same round.
30 |
31 | - Amnesia: a Byzantine process locks a value, although it has locked
32 | another value in the past.
33 |
34 | # TLA+ modules
35 |
36 | - [TendermintAcc_004_draft](TendermintAcc_004_draft.tla) is the protocol
37 | specification,
38 |
39 | - [TendermintAccInv_004_draft](TendermintAccInv_004_draft.tla) contains an
40 | inductive invariant for establishing the protocol safety as well as the
41 | forking cases,
42 |
43 | - `MC_n_f`, e.g., [MC_n4_f1](MC_n4_f1.tla), contains fixed constants for
44 | model checking with the [Apalache model
45 | checker](https://github.com/informalsystems/apalache),
46 |
47 | - [TendermintAccTrace_004_draft](TendermintAccTrace_004_draft.tla) shows how
48 | to restrict the execution space to a fixed sequence of actions (e.g., to
49 | instantiate a counterexample),
50 |
51 | - [TendermintAccDebug_004_draft](TendermintAccDebug_004_draft.tla) contains
52 | the useful definitions for debugging the protocol specification with TLC and
53 | Apalache.
54 |
55 | # Reasoning about fork scenarios
56 |
57 | The theorem statements can be found in
58 | [TendermintAccInv_004_draft.tla](TendermintAccInv_004_draft.tla).
59 |
60 | First, we would like to show that `TypedInv` is an inductive invariant.
61 | Formally, the statement looks as follows:
62 |
63 | ```tla
64 | THEOREM TypedInvIsInductive ==
65 | \/ FaultyQuorum
66 | \//\ Init => TypedInv
67 | /\ TypedInv /\ [Next]_vars => TypedInv'
68 | ```
69 |
70 | When over two-thirds of processes are faulty, `TypedInv` is not inductive.
71 | However, there is no hope to repair the protocol in this case. We run
72 | [Apalache](https://github.com/informalsystems/apalache) to prove this theorem
73 | only for fixed instances of 4 to 5 validators. Apalache does not parse theorem
74 | statements at the moment, so we ran Apalache using a shell script. To find a
75 | parameterized argument, one has to use a theorem prover, e.g., TLAPS.
76 |
77 | Second, we would like to show that the invariant implies `Agreement`, that is,
78 | no fork, provided that less than one third of processes is faulty. By combining
79 | this theorem with the previous theorem, we conclude that the protocol indeed
80 | satisfies Agreement under the condition `LessThanThirdFaulty`.
81 |
82 | ```tla
83 | THEOREM AgreementWhenLessThanThirdFaulty ==
84 | LessThanThirdFaulty /\ TypedInv => Agreement
85 | ```
86 |
87 | Third, in the general case, we either have no fork, or two fork scenarios:
88 |
89 | ```tla
90 | THEOREM AgreementOrFork ==
91 | ~FaultyQuorum /\ TypedInv => Accountability
92 | ```
93 |
94 | # Model checking results
95 |
96 | Check the report on [model checking with Apalache](./results/001indinv-apalache-report.md).
97 |
98 | To run the model checking experiments, use the script:
99 |
100 | ```console
101 | ./run.sh
102 | ```
103 |
104 | This script assumes that the apalache build is available in
105 | `~/devl/apalache-unstable`.
106 |
--------------------------------------------------------------------------------
/ivy-proofs/network_shim.ivy:
--------------------------------------------------------------------------------
1 | #lang ivy1.7
2 | # ---
3 | # layout: page
4 | # title: Network model and network shim
5 | # ---
6 |
7 | # Here we define a network module, which is our model of the network, and a
8 | # shim module that sits on top of the network and which, upon receiving a
9 | # message, calls the appropriate protocol handler.
10 |
11 | include domain_model
12 |
13 | # Here we define an enumeration type for identifying the 3 different types of
14 | # messages that nodes send.
15 | object msg_kind = { # TODO: merge with step_t
16 | type this = {proposal, prevote, precommit}
17 | }
18 |
19 | # Here we define the type of messages `msg`. Its members are structs with the fields described below.
20 | object msg = {
21 | type this = struct {
22 | m_kind : msg_kind,
23 | m_src : node,
24 | m_round : round,
25 | m_value : value,
26 | m_vround : round
27 | }
28 | }
29 |
30 | # This is our model of the network:
31 | isolate net = {
32 |
33 | export action recv(dst:node,v:msg)
34 | action send(src:node,dst:node,v:msg)
35 | # Note that the `recv` action is exported, meaning that it can be called
36 | # non-deterministically by the environment any time it is enabled. In other
37 | # words, a packet that is in flight can be received at any time. In this
38 | # sense, the network is fully asynchronous. Moreover, there is no
39 | # requirement that a given message will be received at all.
40 |
41 | # The state of the network consists of all the packets that have been
42 | # sent so far, along with their destination.
43 | relation sent(V:msg, N:node)
44 |
45 | after init {
46 | sent(V, N) := false
47 | }
48 |
49 | before send {
50 | sent(v,dst) := true
51 | }
52 |
53 | before recv {
54 | require sent(v,dst) # only sent messages can be received.
55 | }
56 | }
57 |
58 | # The network shim sits on top of the network and, upon receiving a message,
59 | # calls the appropriate protocol handler. It also exposes a `broadcast` action
60 | # that sends to all nodes.
61 |
62 | isolate shim = {
63 |
64 | # In order not repeat the same code for each handler, we use a handler
65 | # module parameterized by the type of message it will handle. Below we
66 | # instantiate this module for the 3 types of messages of Tendermint
67 | module handler(p_kind) = {
68 | action handle(dst:node,m:msg)
69 | object spec = {
70 | before handle {
71 | assert sent(m,dst) & m.m_kind = p_kind
72 | }
73 | }
74 | }
75 |
76 | instance proposal_handler : handler(msg_kind.proposal)
77 | instance prevote_handler : handler(msg_kind.prevote)
78 | instance precommit_handler : handler(msg_kind.precommit)
79 |
80 | relation sent(M:msg,N:node)
81 |
82 | action broadcast(src:node,m:msg)
83 | action send(src:node,dst:node,m:msg)
84 |
85 | specification {
86 | after init {
87 | sent(M,D) := false;
88 | }
89 | before broadcast {
90 | sent(m,D) := true
91 | }
92 | before send {
93 | sent(m,dst) := true
94 | }
95 | }
96 |
97 | # Here we give an implementation of it that satisfies its specification:
98 | implementation {
99 |
100 | implement net.recv(dst:node,m:msg) {
101 |
102 | if m.m_kind = msg_kind.proposal {
103 | call proposal_handler.handle(dst,m)
104 | }
105 | else if m.m_kind = msg_kind.prevote {
106 | call prevote_handler.handle(dst,m)
107 | }
108 | else if m.m_kind = msg_kind.precommit {
109 | call precommit_handler.handle(dst,m)
110 | }
111 | }
112 |
113 | implement broadcast { # broadcast sends to all nodes, including the sender.
114 | var iter := node.iter.create(0);
115 | while ~iter.is_end
116 | invariant net.sent(M,D) -> sent(M,D)
117 | {
118 | var n := iter.val;
119 | call net.send(src,n,m);
120 | iter := iter.next;
121 | }
122 | }
123 |
124 | implement send {
125 | call net.send(src,dst,m)
126 | }
127 |
128 | private {
129 | invariant net.sent(M,D) -> sent(M,D)
130 | }
131 | }
132 |
133 | } with net, node # to prove that the shim implementation satisfies the shim specification, we rely on the specification of net and node.
134 |
--------------------------------------------------------------------------------
/spec/light-client/accountability/TendermintAccDebug_004_draft.tla:
--------------------------------------------------------------------------------
1 | ------------------ MODULE TendermintAccDebug_004_draft -------------------------
2 | (*
3 | A few definitions that we use for debugging TendermintAcc3, which do not belong
4 | to the specification itself.
5 |
6 | * Version 3. Modular and parameterized definitions.
7 |
8 | Igor Konnov, 2020.
9 | *)
10 |
11 | EXTENDS TendermintAccInv_004_draft
12 |
13 | \* make them parameters?
14 | NFaultyProposals == 0 \* the number of injected faulty PROPOSE messages
15 | NFaultyPrevotes == 6 \* the number of injected faulty PREVOTE messages
16 | NFaultyPrecommits == 6 \* the number of injected faulty PRECOMMIT messages
17 |
18 | \* Given a set of allowed messages Msgs, this operator produces a function from
19 | \* rounds to sets of messages.
20 | \* Importantly, there will be exactly k messages in the image of msgFun.
21 | \* We use this action to produce k faults in an initial state.
22 | \* @type: (ROUND -> Set(MESSAGE), Set(MESSAGE), Int) => Bool;
23 | ProduceFaults(msgFun, From, k) ==
24 | \E f \in [1..k -> From]:
25 | msgFun = [r \in Rounds |-> {m \in {f[i]: i \in 1..k}: m.round = r}]
26 |
27 | \* As TLC explodes with faults, we may have initial states without faults
28 | InitNoFaults ==
29 | /\ round = [p \in Corr |-> 0]
30 | /\ step = [p \in Corr |-> "PROPOSE"]
31 | /\ decision = [p \in Corr |-> NilValue]
32 | /\ lockedValue = [p \in Corr |-> NilValue]
33 | /\ lockedRound = [p \in Corr |-> NilRound]
34 | /\ validValue = [p \in Corr |-> NilValue]
35 | /\ validRound = [p \in Corr |-> NilRound]
36 | /\ msgsPropose = [r \in Rounds |-> EmptyMsgSet]
37 | /\ msgsPrevote = [r \in Rounds |-> EmptyMsgSet]
38 | /\ msgsPrecommit = [r \in Rounds |-> EmptyMsgSet]
39 | /\ evidence = EmptyMsgSet
40 |
41 | (*
42 | A specialized version of Init that injects NFaultyProposals proposals,
43 | NFaultyPrevotes prevotes, NFaultyPrecommits precommits by the faulty processes
44 | *)
45 | InitFewFaults ==
46 | /\ round = [p \in Corr |-> 0]
47 | /\ step = [p \in Corr |-> "PROPOSE"]
48 | /\ decision = [p \in Corr |-> NilValue]
49 | /\ lockedValue = [p \in Corr |-> NilValue]
50 | /\ lockedRound = [p \in Corr |-> NilRound]
51 | /\ validValue = [p \in Corr |-> NilValue]
52 | /\ validRound = [p \in Corr |-> NilRound]
53 | /\ ProduceFaults(msgsPrevote',
54 | [type: {"PREVOTE"}, src: Faulty, round: Rounds, id: Values],
55 | NFaultyPrevotes)
56 | /\ ProduceFaults(msgsPrecommit',
57 | [type: {"PRECOMMIT"}, src: Faulty, round: Rounds, id: Values],
58 | NFaultyPrecommits)
59 | /\ ProduceFaults(msgsPropose',
60 | [type: {"PROPOSAL"}, src: Faulty, round: Rounds,
61 | proposal: Values, validRound: Rounds \cup {NilRound}],
62 | NFaultyProposals)
63 | /\ evidence = EmptyMsgSet
64 |
65 | \* Add faults incrementally
66 | NextWithFaults ==
67 | \* either the protocol makes a step
68 | \/ Next
69 | \* or a faulty process sends a message
70 | \//\ UNCHANGED <>
72 | /\ \E p \in Faulty:
73 | \E r \in Rounds:
74 | \//\ UNCHANGED <>
75 | /\ \E proposal \in ValidValues \union {NilValue}:
76 | \E vr \in RoundsOrNil:
77 | BroadcastProposal(p, r, proposal, vr)
78 | \//\ UNCHANGED <>
79 | /\ \E id \in ValidValues \union {NilValue}:
80 | BroadcastPrevote(p, r, id)
81 | \//\ UNCHANGED <>
82 | /\ \E id \in ValidValues \union {NilValue}:
83 | BroadcastPrecommit(p, r, id)
84 |
85 | (******************************** PROPERTIES ***************************************)
86 | \* simple reachability properties to see that the spec is progressing
87 | NoPrevote == \A p \in Corr: step[p] /= "PREVOTE"
88 |
89 | NoPrecommit == \A p \in Corr: step[p] /= "PRECOMMIT"
90 |
91 | NoValidPrecommit ==
92 | \A r \in Rounds:
93 | \A m \in msgsPrecommit[r]:
94 | m.id = NilValue \/ m.src \in Faulty
95 |
96 | NoHigherRounds == \A p \in Corr: round[p] < 1
97 |
98 | NoDecision == \A p \in Corr: decision[p] = NilValue
99 |
100 | =============================================================================
101 |
102 |
--------------------------------------------------------------------------------
/spec/abci++/v0.md:
--------------------------------------------------------------------------------
1 | # Tendermint v0 Markdown pseudocode
2 |
3 | This translates the latex code for Tendermint consensus from the Tendermint paper into markdown.
4 |
5 | ### Initialization
6 |
7 | ```go
8 | h_p ← 0
9 | round_p ← 0
10 | step_p is one of {propose, prevote, precommit}
11 | decision_p ← Vector()
12 | lockedRound_p ← -1
13 | lockedValue_p ← nil
14 | validValue_p ← nil
15 | validRound_p ← -1
16 | ```
17 |
18 | ### StartRound(round)
19 |
20 | ```go
21 | function startRound(round) {
22 | round_p ← round
23 | step_p ← propose
24 | if proposer(h_p, round_p) = p {
25 | if validValue_p != nil {
26 | proposal ← validValue_p
27 | } else {
28 | proposal ← getValue()
29 | }
30 | broadcast ⟨PROPOSAL, h_p, round_p, proposal, validRound_p⟩
31 | } else {
32 | schedule OnTimeoutPropose(h_p,round_p) to be executed after timeoutPropose(round_p)
33 | }
34 | }
35 | ```
36 |
37 | ### ReceiveProposal
38 |
39 | In the case where the local node is not locked on any round, the following is ran:
40 |
41 | ```go
42 | upon ⟨PROPOSAL, h_p, round_p, v, −1) from proposer(h_p, round_p) while step_p = propose do {
43 | if valid(v) ∧ (lockedRound_p = −1 ∨ lockedValue_p = v) {
44 | broadcast ⟨PREVOTE, h_p, round_p, id(v)⟩
45 | } else {
46 | broadcast ⟨PREVOTE, h_p, round_p, nil⟩
47 | }
48 | step_p ← prevote
49 | }
50 | ```
51 |
52 | In the case where the node is locked on a round, the following is ran:
53 |
54 | ```go
55 | upon ⟨PROPOSAL, h_p, round_p, v, vr⟩ from proposer(h_p, round_p)
56 | AND 2f + 1 ⟨PREVOTE, h_p, vr, id(v)⟩
57 | while step_p = propose ∧ (vr ≥ 0 ∧ vr < round_p) do {
58 | if valid(v) ∧ (lockedRound_p ≤ vr ∨ lockedValue_p = v) {
59 | broadcast ⟨PREVOTE, h_p, round_p, id(v)⟩
60 | } else {
61 | broadcast ⟨PREVOTE, h_p, round_p, nil⟩
62 | }
63 | step_p ← prevote
64 | }
65 | ```
66 |
67 | ### Prevote timeout
68 |
69 | Upon receiving 2f + 1 prevotes, setup a timeout.
70 |
71 | ```go
72 | upon 2f + 1 ⟨PREVOTE, h_p, vr, *⟩ with step_p = prevote for the first time, do {
73 | schedule OnTimeoutPrevote(h_p, round_p) to be executed after timeoutPrevote(round_p)
74 | }
75 | ```
76 |
77 | with OnTimeoutPrevote defined as:
78 |
79 | ```go
80 | function OnTimeoutPrevote(height, round) {
81 | if (height = h_p && round = round_p && step_p = prevote) {
82 | broadcast ⟨PRECOMMIT, h_p, round_p, nil⟩
83 | step_p ← precommit
84 | }
85 | }
86 | ```
87 |
88 | ### Receiving enough prevotes to precommit
89 |
90 | The following code is ran upon receiving 2f + 1 prevotes for the same block
91 |
92 | ```go
93 | upon ⟨PROPOSAL, h_p, round_p, v, *⟩
94 | from proposer(h_p, round_p)
95 | AND 2f + 1 ⟨PREVOTE, h_p, round_p, id(v)⟩
96 | while valid(v) ∧ step_p >= prevote for the first time do {
97 | if (step_p = prevote) {
98 | lockedValue_p ← v
99 | lockedRound_p ← round_p
100 | broadcast ⟨PRECOMMIT, h_p, round_p, id(v)⟩
101 | step_p ← precommit
102 | }
103 | validValue_p ← v
104 | validRound_p ← round_p
105 | }
106 | ```
107 |
108 | And upon receiving 2f + 1 prevotes for nil:
109 |
110 | ```go
111 | upon 2f + 1 ⟨PREVOTE, h_p, round_p, nil⟩
112 | while step_p = prevote do {
113 | broadcast ⟨PRECOMMIT, h_p, round_p, nil⟩
114 | step_p ← precommit
115 | }
116 | ```
117 |
118 | ### Precommit timeout
119 |
120 | Upon receiving 2f + 1 precommits, setup a timeout.
121 |
122 | ```go
123 | upon 2f + 1 ⟨PRECOMMIT, h_p, vr, *⟩ for the first time, do {
124 | schedule OnTimeoutPrecommit(h_p, round_p) to be executed after timeoutPrecommit(round_p)
125 | }
126 | ```
127 |
128 | with OnTimeoutPrecommit defined as:
129 |
130 | ```go
131 | function OnTimeoutPrecommit(height, round) {
132 | if (height = h_p && round = round_p) {
133 | StartRound(round_p + 1)
134 | }
135 | }
136 | ```
137 |
138 | ### Upon Receiving 2f + 1 precommits
139 |
140 | The following code is ran upon receiving 2f + 1 precommits for the same block
141 |
142 | ```go
143 | upon ⟨PROPOSAL, h_p, r, v, *⟩
144 | from proposer(h_p, r)
145 | AND 2f + 1 ⟨ PRECOMMIT, h_p, r, id(v)⟩
146 | while decision_p[h_p] = nil do {
147 | if (valid(v)) {
148 | decision_p[h_p] ← v
149 | h_p ← h_p + 1
150 | reset lockedRound_p, lockedValue_p,validRound_p and validValue_p to initial values
151 | StartRound(0)
152 | }
153 | }
154 | ```
155 |
156 | If we don't see 2f + 1 precommits for the same block, we wait until we get 2f + 1 precommits, and the timeout occurs.
--------------------------------------------------------------------------------
/spec/light-client/accountability/results/001indinv-apalache-report.md:
--------------------------------------------------------------------------------
1 | # Results of 001indinv-apalache
2 |
3 | ## 1. Awesome plots
4 |
5 | ### 1.1. Time (logarithmic scale)
6 |
7 | 
8 |
9 | ### 1.2. Time (linear)
10 |
11 | 
12 |
13 | ### 1.3. Memory (logarithmic scale)
14 |
15 | 
16 |
17 | ### 1.4. Memory (linear)
18 |
19 | 
20 |
21 | ### 1.5. Number of arena cells (linear)
22 |
23 | 
24 |
25 | ### 1.6. Number of SMT clauses (linear)
26 |
27 | 
28 |
29 | ## 2. Input parameters
30 |
31 | no | filename | tool | timeout | init | inv | next | args
32 | ----|----------------|------------|-----------|------------|------------------|--------|------------------------------
33 | 1 | MC_n4_f1.tla | apalache | 10h | TypedInv | TypedInv | | --length=1 --cinit=ConstInit
34 | 2 | MC_n4_f2.tla | apalache | 10h | TypedInv | TypedInv | | --length=1 --cinit=ConstInit
35 | 3 | MC_n5_f1.tla | apalache | 10h | TypedInv | TypedInv | | --length=1 --cinit=ConstInit
36 | 4 | MC_n5_f2.tla | apalache | 10h | TypedInv | TypedInv | | --length=1 --cinit=ConstInit
37 | 5 | MC_n4_f1.tla | apalache | 20h | Init | TypedInv | | --length=0 --cinit=ConstInit
38 | 6 | MC_n4_f2.tla | apalache | 20h | Init | TypedInv | | --length=0 --cinit=ConstInit
39 | 7 | MC_n5_f1.tla | apalache | 20h | Init | TypedInv | | --length=0 --cinit=ConstInit
40 | 8 | MC_n5_f2.tla | apalache | 20h | Init | TypedInv | | --length=0 --cinit=ConstInit
41 | 9 | MC_n4_f1.tla | apalache | 20h | TypedInv | Agreement | | --length=0 --cinit=ConstInit
42 | 10 | MC_n4_f2.tla | apalache | 20h | TypedInv | Accountability | | --length=0 --cinit=ConstInit
43 | 11 | MC_n5_f1.tla | apalache | 20h | TypedInv | Agreement | | --length=0 --cinit=ConstInit
44 | 12 | MC_n5_f2.tla | apalache | 20h | TypedInv | Accountability | | --length=0 --cinit=ConstInit
45 |
46 | ## 3. Detailed results: 001indinv-apalache-unstable.csv
47 |
48 | 01:no | 02:tool | 03:status | 04:time_sec | 05:depth | 05:mem_kb | 10:ninit_trans | 11:ninit_trans | 12:ncells | 13:nclauses | 14:navg_clause_len
49 | -------|------------|-------------|---------------|------------|-------------|------------------|------------------|-------------|---------------|--------------------
50 | 1 | apalache | NoError | 11m | 1 | 3.0GB | 0 | 0 | 217K | 1.0M | 89
51 | 2 | apalache | NoError | 11m | 1 | 3.0GB | 0 | 0 | 207K | 1.0M | 88
52 | 3 | apalache | NoError | 16m | 1 | 4.0GB | 0 | 0 | 311K | 2.0M | 101
53 | 4 | apalache | NoError | 14m | 1 | 3.0GB | 0 | 0 | 290K | 1.0M | 103
54 | 5 | apalache | NoError | 9s | 0 | 563MB | 0 | 0 | 2.0K | 14K | 42
55 | 6 | apalache | NoError | 10s | 0 | 657MB | 0 | 0 | 2.0K | 28K | 43
56 | 7 | apalache | NoError | 8s | 0 | 635MB | 0 | 0 | 2.0K | 17K | 44
57 | 8 | apalache | NoError | 10s | 0 | 667MB | 0 | 0 | 3.0K | 32K | 45
58 | 9 | apalache | NoError | 5m05s | 0 | 2.0GB | 0 | 0 | 196K | 889K | 108
59 | 10 | apalache | NoError | 8m08s | 0 | 6.0GB | 0 | 0 | 2.0M | 3.0M | 34
60 | 11 | apalache | NoError | 9m09s | 0 | 3.0GB | 0 | 0 | 284K | 1.0M | 128
61 | 12 | apalache | NoError | 14m | 0 | 7.0GB | 0 | 0 | 4.0M | 5.0M | 38
62 |
--------------------------------------------------------------------------------
/spec/p2p/connection.md:
--------------------------------------------------------------------------------
1 | # P2P Multiplex Connection
2 |
3 | ## MConnection
4 |
5 | `MConnection` is a multiplex connection that supports multiple independent streams
6 | with distinct quality of service guarantees atop a single TCP connection.
7 | Each stream is known as a `Channel` and each `Channel` has a globally unique _byte id_.
8 | Each `Channel` also has a relative priority that determines the quality of service
9 | of the `Channel` compared to other `Channel`s.
10 | The _byte id_ and the relative priorities of each `Channel` are configured upon
11 | initialization of the connection.
12 |
13 | The `MConnection` supports three packet types:
14 |
15 | - Ping
16 | - Pong
17 | - Msg
18 |
19 | ### Ping and Pong
20 |
21 | The ping and pong messages consist of writing a single byte to the connection; 0x1 and 0x2, respectively.
22 |
23 | When we haven't received any messages on an `MConnection` in time `pingTimeout`, we send a ping message.
24 | When a ping is received on the `MConnection`, a pong is sent in response only if there are no other messages
25 | to send and the peer has not sent us too many pings (TODO).
26 |
27 | If a pong or message is not received in sufficient time after a ping, the peer is disconnected from.
28 |
29 | ### Msg
30 |
31 | Messages in channels are chopped into smaller `msgPacket`s for multiplexing.
32 |
33 | ```go
34 | type msgPacket struct {
35 | ChannelID byte
36 | EOF byte // 1 means message ends here.
37 | Bytes []byte
38 | }
39 | ```
40 |
41 | The `msgPacket` is serialized using [Proto3](https://developers.google.com/protocol-buffers/docs/proto3).
42 | The received `Bytes` of a sequential set of packets are appended together
43 | until a packet with `EOF=1` is received, then the complete serialized message
44 | is returned for processing by the `onReceive` function of the corresponding channel.
45 |
46 | ### Multiplexing
47 |
48 | Messages are sent from a single `sendRoutine`, which loops over a select statement and results in the sending
49 | of a ping, a pong, or a batch of data messages. The batch of data messages may include messages from multiple channels.
50 | Message bytes are queued for sending in their respective channel, with each channel holding one unsent message at a time.
51 | Messages are chosen for a batch one at a time from the channel with the lowest ratio of recently sent bytes to channel priority.
52 |
53 | ## Sending Messages
54 |
55 | There are two methods for sending messages:
56 |
57 | ```go
58 | func (m MConnection) Send(chID byte, msg interface{}) bool {}
59 | func (m MConnection) TrySend(chID byte, msg interface{}) bool {}
60 | ```
61 |
62 | `Send(chID, msg)` is a blocking call that waits until `msg` is successfully queued
63 | for the channel with the given id byte `chID`. The message `msg` is serialized
64 | using the `tendermint/go-amino` submodule's `WriteBinary()` reflection routine.
65 |
66 | `TrySend(chID, msg)` is a nonblocking call that queues the message msg in the channel
67 | with the given id byte chID if the queue is not full; otherwise it returns false immediately.
68 |
69 | `Send()` and `TrySend()` are also exposed for each `Peer`.
70 |
71 | ## Peer
72 |
73 | Each peer has one `MConnection` instance, and includes other information such as whether the connection
74 | was outbound, whether the connection should be recreated if it closes, various identity information about the node,
75 | and other higher level thread-safe data used by the reactors.
76 |
77 | ## Switch/Reactor
78 |
79 | The `Switch` handles peer connections and exposes an API to receive incoming messages
80 | on `Reactors`. Each `Reactor` is responsible for handling incoming messages of one
81 | or more `Channels`. So while sending outgoing messages is typically performed on the peer,
82 | incoming messages are received on the reactor.
83 |
84 | ```go
85 | // Declare a MyReactor reactor that handles messages on MyChannelID.
86 | type MyReactor struct{}
87 |
88 | func (reactor MyReactor) GetChannels() []*ChannelDescriptor {
89 | return []*ChannelDescriptor{ChannelDescriptor{ID:MyChannelID, Priority: 1}}
90 | }
91 |
92 | func (reactor MyReactor) Receive(chID byte, peer *Peer, msgBytes []byte) {
93 | r, n, err := bytes.NewBuffer(msgBytes), new(int64), new(error)
94 | msgString := ReadString(r, n, err)
95 | fmt.Println(msgString)
96 | }
97 |
98 | // Other Reactor methods omitted for brevity
99 | ...
100 |
101 | switch := NewSwitch([]Reactor{MyReactor{}})
102 |
103 | ...
104 |
105 | // Send a random message to all outbound connections
106 | for _, peer := range switch.Peers().List() {
107 | if peer.IsOutbound() {
108 | peer.Send(MyChannelID, "Here's a random message")
109 | }
110 | }
111 | ```
112 |
--------------------------------------------------------------------------------
/spec/core/state.md:
--------------------------------------------------------------------------------
1 | # State
2 |
3 | The state contains information whose cryptographic digest is included in block headers, and thus is
4 | necessary for validating new blocks. For instance, the validators set and the results of
5 | transactions are never included in blocks, but their Merkle roots are:
6 | the state keeps track of them.
7 |
8 | The `State` object itself is an implementation detail, since it is never
9 | included in a block or gossiped over the network, and we never compute
10 | its hash. The persistence or query interface of the `State` object
11 | is an implementation detail and not included in the specification.
12 | However, the types in the `State` object are part of the specification, since
13 | the Merkle roots of the `State` objects are included in blocks and values are used during
14 | validation.
15 |
16 | ```go
17 | type State struct {
18 | ChainID string
19 | InitialHeight int64
20 |
21 | LastBlockHeight int64
22 | LastBlockID types.BlockID
23 | LastBlockTime time.Time
24 |
25 | Version Version
26 | LastResults []Result
27 | AppHash []byte
28 |
29 | LastValidators ValidatorSet
30 | Validators ValidatorSet
31 | NextValidators ValidatorSet
32 |
33 | ConsensusParams ConsensusParams
34 | }
35 | ```
36 |
37 | The chain ID and initial height are taken from the genesis file, and not changed again. The
38 | initial height will be `1` in the typical case, `0` is an invalid value.
39 |
40 | Note there is a hard-coded limit of 10000 validators. This is inherited from the
41 | limit on the number of votes in a commit.
42 |
43 | Further information on [`Validator`'s](./data_structures.md#validator),
44 | [`ValidatorSet`'s](./data_structures.md#validatorset) and
45 | [`ConsensusParams`'s](./data_structures.md#consensusparams) can
46 | be found in [data structures](./data_structures.md)
47 |
48 | ## Execution
49 |
50 | State gets updated at the end of executing a block. Of specific interest is `ResponseEndBlock` and
51 | `ResponseCommit`
52 |
53 | ```go
54 | type ResponseEndBlock struct {
55 | ValidatorUpdates []ValidatorUpdate `protobuf:"bytes,1,rep,name=validator_updates,json=validatorUpdates,proto3" json:"validator_updates"`
56 | ConsensusParamUpdates *types1.ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_updates,json=consensusParamUpdates,proto3" json:"consensus_param_updates,omitempty"`
57 | Events []Event `protobuf:"bytes,3,rep,name=events,proto3" json:"events,omitempty"`
58 | }
59 | ```
60 |
61 | where
62 |
63 | ```go
64 | type ValidatorUpdate struct {
65 | PubKey crypto.PublicKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"`
66 | Power int64 `protobuf:"varint,2,opt,name=power,proto3" json:"power,omitempty"`
67 | }
68 | ```
69 |
70 | and
71 |
72 | ```go
73 | type ResponseCommit struct {
74 | // reserve 1
75 | Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
76 | RetainHeight int64 `protobuf:"varint,3,opt,name=retain_height,json=retainHeight,proto3" json:"retain_height,omitempty"`
77 | }
78 | ```
79 |
80 | `ValidatorUpdates` are used to add and remove validators to the current set as well as update
81 | validator power. Setting validator power to 0 in `ValidatorUpdate` will cause the validator to be
82 | removed. `ConsensusParams` are safely copied across (i.e. if a field is nil it gets ignored) and the
83 | `Data` from the `ResponseCommit` is used as the `AppHash`
84 |
85 | ## Version
86 |
87 | ```go
88 | type Version struct {
89 | consensus Consensus
90 | software string
91 | }
92 | ```
93 |
94 | [`Consensus`](./data_structures.md#version) contains the protocol version for the blockchain and the
95 | application.
96 |
97 | ## Block
98 |
99 | The total size of a block is limited in bytes by the `ConsensusParams.Block.MaxBytes`.
100 | Proposed blocks must be less than this size, and will be considered invalid
101 | otherwise.
102 |
103 | Blocks should additionally be limited by the amount of "gas" consumed by the
104 | transactions in the block, though this is not yet implemented.
105 |
106 | ## Evidence
107 |
108 | For evidence in a block to be valid, it must satisfy:
109 |
110 | ```go
111 | block.Header.Time-evidence.Time < ConsensusParams.Evidence.MaxAgeDuration &&
112 | block.Header.Height-evidence.Height < ConsensusParams.Evidence.MaxAgeNumBlocks
113 | ```
114 |
115 | A block must not contain more than `ConsensusParams.Evidence.MaxBytes` of evidence. This is
116 | implemented to mitigate spam attacks.
117 |
118 | ## Validator
119 |
120 | Validators from genesis file and `ResponseEndBlock` must have pubkeys of type ∈
121 | `ConsensusParams.Validator.PubKeyTypes`.
122 |
--------------------------------------------------------------------------------
/spec/abci++/v1.md:
--------------------------------------------------------------------------------
1 | # Tendermint v1 Markdown pseudocode
2 |
3 | This adds hooks for the existing ABCI to the prior pseudocode
4 |
5 | ### Initialization
6 |
7 | ```go
8 | h_p ← 0
9 | round_p ← 0
10 | step_p is one of {propose, prevote, precommit}
11 | decision_p ← Vector()
12 | lockedValue_p ← nil
13 | validValue_p ← nil
14 | validRound_p ← -1
15 | ```
16 |
17 | ### StartRound(round)
18 |
19 | ```go
20 | function startRound(round) {
21 | round_p ← round
22 | step_p ← propose
23 | if proposer(h_p, round_p) = p {
24 | if validValue_p != nil {
25 | proposal ← validValue_p
26 | } else {
27 | txdata ← mempool.GetBlock()
28 | // getBlockProposal fills in header
29 | proposal ← getBlockProposal(txdata)
30 | }
31 | broadcast ⟨PROPOSAL, h_p, round_p, proposal, validRound_p⟩
32 | } else {
33 | schedule OnTimeoutPropose(h_p,round_p) to be executed after timeoutPropose(round_p)
34 | }
35 | }
36 | ```
37 |
38 | ### ReceiveProposal
39 |
40 | In the case where the local node is not locked on any round, the following is ran:
41 |
42 | ```go
43 | upon ⟨PROPOSAL, h_p, round_p, v, −1) from proposer(h_p, round_p) while step_p = propose do {
44 | if valid(v) ∧ (lockedRound_p = −1 ∨ lockedValue_p = v) {
45 | broadcast ⟨PREVOTE, h_p, round_p, id(v)⟩
46 | } else {
47 | broadcast ⟨PREVOTE, h_p, round_p, nil⟩
48 | }
49 | step_p ← prevote
50 | }
51 | ```
52 |
53 | In the case where the node is locked on a round, the following is ran:
54 |
55 | ```go
56 | upon ⟨PROPOSAL, h_p, round_p, v, vr⟩
57 | from proposer(h_p, round_p)
58 | AND 2f + 1 ⟨PREVOTE, h_p, vr, id(v)⟩
59 | while step_p = propose ∧ (vr ≥ 0 ∧ vr < round_p) do {
60 | if valid(v) ∧ (lockedRound_p ≤ vr ∨ lockedValue_p = v) {
61 | broadcast ⟨PREVOTE, h_p, round_p, id(v)⟩
62 | } else {
63 | broadcast ⟨PREVOTE, h_p, round_p, nil⟩
64 | }
65 | step_p ← prevote
66 | }
67 | ```
68 |
69 | ### Prevote timeout
70 |
71 | Upon receiving 2f + 1 prevotes, setup a timeout.
72 |
73 | ```go
74 | upon 2f + 1 ⟨PREVOTE, h_p, vr, -1⟩
75 | with step_p = prevote for the first time, do {
76 | schedule OnTimeoutPrevote(h_p, round_p) to be executed after timeoutPrevote(round_p)
77 | }
78 | ```
79 |
80 | with OnTimeoutPrevote defined as:
81 |
82 | ```go
83 | function OnTimeoutPrevote(height, round) {
84 | if (height = h_p && round = round_p && step_p = prevote) {
85 | broadcast ⟨PRECOMMIT, h_p, round_p, nil⟩
86 | step_p ← precommit
87 | }
88 | }
89 | ```
90 |
91 | ### Receiving enough prevotes to precommit
92 |
93 | The following code is ran upon receiving 2f + 1 prevotes for the same block
94 |
95 | ```go
96 | upon ⟨PROPOSAL, h_p, round_p, v, *⟩
97 | from proposer(h_p, round_p)
98 | AND 2f + 1 ⟨PREVOTE, h_p, vr, id(v)⟩
99 | while valid(v) ∧ step_p >= prevote for the first time do {
100 | if (step_p = prevote) {
101 | lockedValue_p ← v
102 | lockedRound_p ← round_p
103 | broadcast ⟨PRECOMMIT, h_p, round_p, id(v)⟩
104 | step_p ← precommit
105 | }
106 | validValue_p ← v
107 | validRound_p ← round_p
108 | }
109 | ```
110 |
111 | And upon receiving 2f + 1 prevotes for nil:
112 |
113 | ```go
114 | upon 2f + 1 ⟨PREVOTE, h_p, round_p, nil⟩
115 | while step_p = prevote do {
116 | broadcast ⟨PRECOMMIT, h_p, round_p, nil⟩
117 | step_p ← precommit
118 | }
119 | ```
120 |
121 | ### Precommit timeout
122 |
123 | Upon receiving 2f + 1 precommits, setup a timeout.
124 |
125 | ```go
126 | upon 2f + 1 ⟨PRECOMMIT, h_p, vr, *⟩ for the first time, do {
127 | schedule OnTimeoutPrecommit(h_p, round_p) to be executed after timeoutPrecommit(round_p)
128 | }
129 | ```
130 |
131 | with OnTimeoutPrecommit defined as:
132 |
133 | ```go
134 | function OnTimeoutPrecommit(height, round) {
135 | if (height = h_p && round = round_p) {
136 | StartRound(round_p + 1)
137 | }
138 | }
139 | ```
140 |
141 | ### Upon Receiving 2f + 1 precommits
142 |
143 | The following code is ran upon receiving 2f + 1 precommits for the same block
144 |
145 | ```go
146 | upon ⟨PROPOSAL, h_p, r, v, *⟩
147 | from proposer(h_p, r)
148 | AND 2f + 1 ⟨ PRECOMMIT, h_p, r, id(v)⟩
149 | while decision_p[h_p] = nil do {
150 | if (valid(v)) {
151 | decision_p[h_p] ← v
152 | h_p ← h_p + 1
153 | reset lockedRound_p, lockedValue_p,validRound_p and validValue_p to initial values
154 | ABCI.BeginBlock(v.header)
155 | ABCI.DeliverTxs(v.data)
156 | ABCI.EndBlock()
157 | StartRound(0)
158 | }
159 | }
160 | ```
161 |
162 | If we don't see 2f + 1 precommits for the same block, we wait until we get 2f + 1 precommits, and the timeout occurs.
--------------------------------------------------------------------------------
/ivy-proofs/tendermint_test.ivy:
--------------------------------------------------------------------------------
1 | #lang ivy1.7
2 |
3 | include tendermint
4 | include abstract_tendermint
5 |
6 | isolate ghost_ = {
7 | instantiate abstract_tendermint
8 | }
9 |
10 | isolate protocol = {
11 | instantiate tendermint(ghost_) # here we instantiate the parameter of the tendermint module with `ghost_`; however note that we don't extract any code for `ghost_` (it's not in the list of object in the extract, and it's thus sliced away).
12 | implementation {
13 | definition init_val(n:node) = <<< `n`%2 >>>
14 | }
15 | # attribute test = impl
16 | } with ghost_, shim, value, round, proposers
17 |
18 | # Here we run a simple scenario that exhibits an execution in which nodes make
19 | # a decision. We do this to rule out trivial modeling errors.
20 |
21 | # One option to check that this scenario is valid is to run it in Ivy's REPL.
22 | # For this, first compile the scenario:
23 | #```ivyc target=repl isolate=code trace=true tendermint_test.ivy
24 | # Then, run the produced binary (e.g. for 4 nodes):
25 | #``` ./tendermint_test 4
26 | # Finally, call the action:
27 | #``` scenarios.scenario_1
28 | # Note that Ivy will check at runtime that all action preconditions are
29 | # satisfied. For example, runing the scenario twice will cause a violation of
30 | # the precondition of the `start` action, because a node cannot start twice
31 | # (see `require ~_has_started` in action `start`).
32 |
33 | # Another possibility would be to run `ivy_check` on the scenario, but that
34 | # does not seem to work at the moment.
35 |
36 | isolate scenarios = {
37 | individual all:nset # will be used as parameter to actions requiring a quorum
38 |
39 | after init {
40 | var iter := node.iter.create(0);
41 | while ~iter.is_end
42 | {
43 | all := all.insert(iter.val);
44 | iter := iter.next;
45 | };
46 | assert nset.is_quorum(all); # we can also use asserts to make sure we are getting what we expect
47 | }
48 |
49 | export action scenario_1 = {
50 | # all nodes start:
51 | var iter := node.iter.create(0);
52 | while ~iter.is_end
53 | {
54 | call protocol.server.start(iter.val);
55 | iter := iter.next;
56 | };
57 | # all nodes receive the leader's proposal:
58 | var m:msg;
59 | m.m_kind := msg_kind.proposal;
60 | m.m_src := 0;
61 | m.m_round := 0;
62 | m.m_value := 0;
63 | m.m_vround := round.minus_one;
64 | iter := node.iter.create(0);
65 | while ~iter.is_end
66 | {
67 | call net.recv(iter.val,m);
68 | iter := iter.next;
69 | };
70 | # all nodes prevote:
71 | iter := node.iter.create(0);
72 | while ~iter.is_end
73 | {
74 | call protocol.server.l_22(iter.val,0);
75 | iter := iter.next;
76 | };
77 | # all nodes receive each other's prevote messages;
78 | m.m_kind := msg_kind.prevote;
79 | m.m_vround := 0;
80 | iter := node.iter.create(0);
81 | while ~iter.is_end
82 | {
83 | var iter2 := node.iter.create(0); # the sender
84 | while ~iter2.is_end
85 | {
86 | m.m_src := iter2.val;
87 | call net.recv(iter.val,m);
88 | iter2 := iter2.next;
89 | };
90 | iter := iter.next;
91 | };
92 | # all nodes precommit:
93 | iter := node.iter.create(0);
94 | while ~iter.is_end
95 | {
96 | call protocol.server.l_36(iter.val,0,0,all);
97 | iter := iter.next;
98 | };
99 | # all nodes receive each other's pre-commits
100 | m.m_kind := msg_kind.precommit;
101 | iter := node.iter.create(0);
102 | while ~iter.is_end
103 | {
104 | var iter2 := node.iter.create(0); # the sender
105 | while ~iter2.is_end
106 | {
107 | m.m_src := iter2.val;
108 | call net.recv(iter.val,m);
109 | iter2 := iter2.next;
110 | };
111 | iter := iter.next;
112 | };
113 | # now all nodes can decide:
114 | iter := node.iter.create(0);
115 | while ~iter.is_end
116 | {
117 | call protocol.server.l_49_decide(iter.val,0,0,all);
118 | iter := iter.next;
119 | };
120 | }
121 |
122 | # TODO: add more scenarios
123 |
124 | } with round, node, proposers, value, nset, protocol, shim, net
125 |
126 | # extract code = protocol, shim, round, node
127 | extract code = round, node, proposers, value, nset, protocol, shim, net, scenarios
128 |
--------------------------------------------------------------------------------
/spec/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | title: Overview
4 | parent:
5 | title: Spec
6 | order: 7
7 | ---
8 |
9 | **THIS REPOSITORY HAS BEEN ARCHIVED. THE TENDERMINT SPECIFICATION IS NOW LOCATED IN THE [TENDERMINT/TENDERMINT](https://github.com/tendermint/tendermint/tree/master/spec) REPOSITORY.**
10 |
11 | ---
12 |
13 | # Tendermint Spec
14 |
15 | This is a Markdown specification of the Tendermint blockchain.
16 | It defines the base data structures, how they are validated,
17 | and how they are communicated over the network.
18 |
19 | If you find discrepancies between the spec and the code that
20 | do not have an associated issue or pull request on github,
21 | please submit them to our [bug bounty](https://tendermint.com/security)!
22 |
23 | ## Contents
24 |
25 | - [Overview](#overview)
26 |
27 | ### Data Structures
28 |
29 | - [Encoding and Digests](./core/encoding.md)
30 | - [Blockchain](./core/data_structures.md)
31 | - [State](./core/state.md)
32 |
33 | ### Consensus Protocol
34 |
35 | - [Consensus Algorithm](./consensus/consensus.md)
36 | - [Creating a proposal](./consensus/creating-proposal.md)
37 | - [Time](./consensus/bft-time.md)
38 | - [Light-Client](./consensus/light-client/README.md)
39 |
40 | ### P2P and Network Protocols
41 |
42 | - [The Base P2P Layer](./p2p/node.md): multiplex the protocols ("reactors") on authenticated and encrypted TCP connections
43 | - [Peer Exchange (PEX)](./p2p/messages/pex.md): gossip known peer addresses so peers can find each other
44 | - [Block Sync](./p2p/messages/block-sync.md): gossip blocks so peers can catch up quickly
45 | - [Consensus](./p2p/messages/consensus.md): gossip votes and block parts so new blocks can be committed
46 | - [Mempool](./p2p/messages/mempool.md): gossip transactions so they get included in blocks
47 | - [Evidence](./p2p/messages/evidence.md): sending invalid evidence will stop the peer
48 |
49 | ### RPC
50 |
51 | - [RPC SPEC](./rpc/README.md): Specification of the Tendermint remote procedure call interface.
52 |
53 | ### Software
54 |
55 | - [ABCI](./abci/README.md): Details about interactions between the
56 | application and consensus engine over ABCI
57 | - [ABCI++](./abci++/README.md): Specification of interactions between the
58 | application and consensus engine over ABCI++
59 | - [Write-Ahead Log](./consensus/wal.md): Details about how the consensus
60 | engine preserves data and recovers from crash failures
61 |
62 | ## Overview
63 |
64 | Tendermint provides Byzantine Fault Tolerant State Machine Replication using
65 | hash-linked batches of transactions. Such transaction batches are called "blocks".
66 | Hence, Tendermint defines a "blockchain".
67 |
68 | Each block in Tendermint has a unique index - its Height.
69 | Height's in the blockchain are monotonic.
70 | Each block is committed by a known set of weighted Validators.
71 | Membership and weighting within this validator set may change over time.
72 | Tendermint guarantees the safety and liveness of the blockchain
73 | so long as less than 1/3 of the total weight of the Validator set
74 | is malicious or faulty.
75 |
76 | A commit in Tendermint is a set of signed messages from more than 2/3 of
77 | the total weight of the current Validator set. Validators take turns proposing
78 | blocks and voting on them. Once enough votes are received, the block is considered
79 | committed. These votes are included in the _next_ block as proof that the previous block
80 | was committed - they cannot be included in the current block, as that block has already been
81 | created.
82 |
83 | Once a block is committed, it can be executed against an application.
84 | The application returns results for each of the transactions in the block.
85 | The application can also return changes to be made to the validator set,
86 | as well as a cryptographic digest of its latest state.
87 |
88 | Tendermint is designed to enable efficient verification and authentication
89 | of the latest state of the blockchain. To achieve this, it embeds
90 | cryptographic commitments to certain information in the block "header".
91 | This information includes the contents of the block (eg. the transactions),
92 | the validator set committing the block, as well as the various results returned by the application.
93 | Note, however, that block execution only occurs _after_ a block is committed.
94 | Thus, application results can only be included in the _next_ block.
95 |
96 | Also note that information like the transaction results and the validator set are never
97 | directly included in the block - only their cryptographic digests (Merkle roots) are.
98 | Hence, verification of a block requires a separate data structure to store this information.
99 | We call this the `State`. Block verification also requires access to the previous block.
100 |
--------------------------------------------------------------------------------
/spec/light-client/supervisor/supervisor_002_draft.md:
--------------------------------------------------------------------------------
1 | # Draft of Light Client Supervisor for discussion
2 |
3 | ## Modification to the initialization
4 |
5 | The lightclient is initialized with LCInitData
6 |
7 | ### **[LC-DATA-INIT.2]**
8 |
9 | ```go
10 | type LCInitData struct {
11 | TrustedBlock LightBlock
12 | Genesis GenesisDoc
13 | TrustedHash []byte
14 | TrustedHeight int64
15 | }
16 | ```
17 |
18 | where only one of the components must be provided. `GenesisDoc` is
19 | defined in the [Tendermint
20 | Types](https://github.com/tendermint/tendermint/blob/master/types/genesis.go).
21 |
22 |
23 | ### Initialization
24 |
25 | The light client is based on subjective initialization. It has to
26 | trust the initial data given to it by the user. It cannot perform any
27 | detection of an attack yet instead requires an initial point of trust.
28 | There are three forms of initial data which are used to obtain the
29 | first trusted block:
30 |
31 | - A trusted block from a prior initialization
32 | - A trusted height and hash
33 | - A genesis file
34 |
35 | The golang light client implementation checks this initial data in that
36 | order; first attempting to find a trusted block from the trusted store,
37 | then acquiring a light block from the primary at the trusted height and matching
38 | the hash, or finally checking for a genesis file to verify the initial header.
39 |
40 | The light client doesn't need to check if the trusted block is within the
41 | trusted period because it already trusts it, however, if the light block is
42 | outside the trust period, there is a higher chance the light client won't be
43 | able to verify anything.
44 |
45 | Cross-checking this trusted block with providers upon initialization is helpful
46 | for ensuring that the node is responsive and correctly configured but does not
47 | increase trust since proving a conflicting block is a
48 | [light client attack](https://github.com/tendermint/spec/blob/master/spec/light-client/detection/detection_003_reviewed.md#tmbc-lc-attack1)
49 | and not just a [bogus](https://github.com/tendermint/spec/blob/master/spec/light-client/detection/detection_003_reviewed.md#tmbc-bogus1) block could result in
50 | performing backwards verification beyond the trusted period, thus a fruitless
51 | endeavour.
52 |
53 | However, with the notion of it's better to fail earlier than later, the golang
54 | light client implementation will perform a consistency check on all providers
55 | and will error if one returns a different header, allowing the user
56 | the opportunity to reinitialize.
57 |
58 | #### **[LC-FUNC-INIT.2]:**
59 |
60 | ```go
61 | func InitLightClient(initData LCInitData) (LightStore, Error) {
62 | var initialBlock LightBlock
63 |
64 | switch {
65 | case LCInitData.TrustedBlock != nil:
66 | // we trust the block from a prior initialization
67 | initialBlock = LCInitData.TrustedBlock
68 |
69 | case LCInitData.TrustedHash != nil:
70 | untrustedBlock := FetchLightBlock(PeerList.Primary(), LCInitData.TrustedHeight)
71 |
72 |
73 | // verify that the hashes match
74 | if untrustedBlock.Hash() != LCInitData.TrustedHash {
75 | return nil, Error("Primary returned block with different hash")
76 | }
77 | // after checking the hash we now trust the block
78 | initialBlock = untrustedBlock
79 | }
80 | case LCInitData.Genesis != nil:
81 | untrustedBlock := FetchLightBlock(PeerList.Primary(), LCInitData.Genesis.InitialHeight)
82 |
83 | // verify that 2/3+ of the validator set signed the untrustedBlock
84 | if err := VerifyCommitFull(untrustedBlock.Commit, LCInitData.Genesis.Validators); err != nil {
85 | return nil, err
86 | }
87 |
88 | // we can now trust the block
89 | initialBlock = untrustedBlock
90 | default:
91 | return nil, Error("No initial data was provided")
92 |
93 | // This is done in the golang version but is optional and not strictly part of the protocol
94 | if err := CrossCheck(initialBlock, PeerList.Witnesses()); err != nil {
95 | return nil, err
96 | }
97 |
98 | // initialize light store
99 | lightStore := new LightStore;
100 | lightStore.Add(newBlock);
101 | return (lightStore, OK);
102 | }
103 |
104 | func CrossCheck(lb LightBlock, witnesses []Provider) error {
105 | for _, witness := range witnesses {
106 | witnessBlock := FetchLightBlock(witness, lb.Height)
107 |
108 | if witnessBlock.Hash() != lb.Hash() {
109 | return Error("Witness has different block")
110 | }
111 | }
112 | return OK
113 | }
114 |
115 | ```
116 |
117 | - Implementation remark
118 | - none
119 | - Expected precondition
120 | - *LCInitData* contains either a genesis file of a lightblock
121 | - if genesis it passes `ValidateAndComplete()` see [Tendermint](https://informal.systems)
122 | - Expected postcondition
123 | - *lightStore* initialized with trusted lightblock. It has either been
124 | cross-checked (from genesis) or it has initial trust from the
125 | user.
126 | - Error condition
127 | - if precondition is violated
128 | - empty peerList
129 |
130 | ----
131 |
132 |
--------------------------------------------------------------------------------
/spec/abci/client-server.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 3
3 | title: Client and Server
4 | ---
5 |
6 | # Client and Server
7 |
8 | This section is for those looking to implement their own ABCI Server, perhaps in
9 | a new programming language.
10 |
11 | You are expected to have read [ABCI Methods and Types](./abci.md) and [ABCI
12 | Applications](./apps.md).
13 |
14 | ## Message Protocol
15 |
16 | The message protocol consists of pairs of requests and responses defined in the
17 | [protobuf file](../../proto/tendermint/abci/types.proto).
18 |
19 | Some messages have no fields, while others may include byte-arrays, strings, integers,
20 | or custom protobuf types.
21 |
22 | For more details on protobuf, see the [documentation](https://developers.google.com/protocol-buffers/docs/overview).
23 |
24 | For each request, a server should respond with the corresponding
25 | response, where the order of requests is preserved in the order of
26 | responses.
27 |
28 | ## Server Implementations
29 |
30 | To use ABCI in your programming language of choice, there must be a ABCI
31 | server in that language. Tendermint supports three implementations of the ABCI, written in Go:
32 |
33 | - In-process ([Golang](https://github.com/tendermint/tendermint/tree/master/abci), [Rust](https://github.com/tendermint/rust-abci))
34 | - ABCI-socket
35 | - GRPC
36 |
37 | The latter two can be tested using the `abci-cli` by setting the `--abci` flag
38 | appropriately (ie. to `socket` or `grpc`).
39 |
40 | See examples, in various stages of maintenance, in
41 | [Go](https://github.com/tendermint/tendermint/tree/master/abci/server),
42 | [JavaScript](https://github.com/tendermint/js-abci),
43 | [C++](https://github.com/mdyring/cpp-tmsp), and
44 | [Java](https://github.com/jTendermint/jabci).
45 |
46 | ### In Process
47 |
48 | The simplest implementation uses function calls within Golang.
49 | This means ABCI applications written in Golang can be compiled with Tendermint Core and run as a single binary.
50 |
51 | ### GRPC
52 |
53 | If GRPC is available in your language, this is the easiest approach,
54 | though it will have significant performance overhead.
55 |
56 | To get started with GRPC, copy in the [protobuf
57 | file](../../proto/tendermint/abci/types.proto) and compile it using the GRPC
58 | plugin for your language. For instance, for golang, the command is `protoc
59 | --go_out=plugins=grpc:. types.proto`. See the [grpc documentation for more
60 | details](http://www.grpc.io/docs/). `protoc` will autogenerate all the
61 | necessary code for ABCI client and server in your language, including whatever
62 | interface your application must satisfy to be used by the ABCI server for
63 | handling requests.
64 |
65 | Note the length-prefixing used in the socket implementation (TSP) does not apply for GRPC.
66 |
67 | ### TSP
68 |
69 | Tendermint Socket Protocol is an asynchronous, raw socket server which provides ordered message passing over unix or tcp.
70 | Messages are serialized using Protobuf3 and length-prefixed with a [signed Varint](https://developers.google.com/protocol-buffers/docs/encoding?csw=1#signed-integers)
71 |
72 | If GRPC is not available in your language, or you require higher
73 | performance, or otherwise enjoy programming, you may implement your own
74 | ABCI server using the Tendermint Socket Protocol. The first step is still to auto-generate the relevant data
75 | types and codec in your language using `protoc`. In addition to being proto3 encoded, messages coming over
76 | the socket are length-prefixed to facilitate use as a streaming protocol. proto3 doesn't have an
77 | official length-prefix standard, so we use our own. The first byte in
78 | the prefix represents the length of the Big Endian encoded length. The
79 | remaining bytes in the prefix are the Big Endian encoded length.
80 |
81 | For example, if the proto3 encoded ABCI message is 0xDEADBEEF (4
82 | bytes), the length-prefixed message is 0x0104DEADBEEF. If the proto3
83 | encoded ABCI message is 65535 bytes long, the length-prefixed message
84 | would be like 0x02FFFF....
85 |
86 | The benefit of using this `varint` encoding over the old version (where integers were encoded as `` is that
87 | it is the standard way to encode integers in Protobuf. It is also generally shorter.
88 |
89 | As noted above, this prefixing does not apply for GRPC.
90 |
91 | An ABCI server must also be able to support multiple connections, as
92 | Tendermint uses four connections.
93 |
94 | ### Async vs Sync
95 |
96 | The main ABCI server (ie. non-GRPC) provides ordered asynchronous messages.
97 | This is useful for DeliverTx and CheckTx, since it allows Tendermint to forward
98 | transactions to the app before it's finished processing previous ones.
99 |
100 | Thus, DeliverTx and CheckTx messages are sent asynchronously, while all other
101 | messages are sent synchronously.
102 |
103 | ## Client
104 |
105 | There are currently two use-cases for an ABCI client. One is a testing
106 | tool, as in the `abci-cli`, which allows ABCI requests to be sent via
107 | command line. The other is a consensus engine, such as Tendermint Core,
108 | which makes requests to the application every time a new transaction is
109 | received or a block is committed.
110 |
111 | It is unlikely that you will need to implement a client. For details of
112 | our client, see
113 | [here](https://github.com/tendermint/tendermint/tree/master/abci/client).
114 |
--------------------------------------------------------------------------------
/spec/consensus/consensus-paper/latex8.sty:
--------------------------------------------------------------------------------
1 | % ---------------------------------------------------------------
2 | %
3 | % $Id: latex8.sty,v 1.2 1995/09/15 15:31:13 ienne Exp $
4 | %
5 | % by Paolo.Ienne@di.epfl.ch
6 | %
7 | % ---------------------------------------------------------------
8 | %
9 | % no guarantee is given that the format corresponds perfectly to
10 | % IEEE 8.5" x 11" Proceedings, but most features should be ok.
11 | %
12 | % ---------------------------------------------------------------
13 | % with LaTeX2e:
14 | % =============
15 | %
16 | % use as
17 | % \documentclass[times,10pt,twocolumn]{article}
18 | % \usepackage{latex8}
19 | % \usepackage{times}
20 | %
21 | % ---------------------------------------------------------------
22 |
23 | % with LaTeX 2.09:
24 | % ================
25 | %
26 | % use as
27 | % \documentstyle[times,art10,twocolumn,latex8]{article}
28 | %
29 | % ---------------------------------------------------------------
30 | % with both versions:
31 | % ===================
32 | %
33 | % specify \pagestyle{empty} to omit page numbers in the final
34 | % version
35 | %
36 | % specify references as
37 | % \bibliographystyle{latex8}
38 | % \bibliography{...your files...}
39 | %
40 | % use Section{} and SubSection{} instead of standard section{}
41 | % and subsection{} to obtain headings in the form
42 | % "1.3. My heading"
43 | %
44 | % ---------------------------------------------------------------
45 |
46 | \typeout{IEEE 8.5 x 11-Inch Proceedings Style `latex8.sty'.}
47 |
48 | % ten point helvetica bold required for captions
49 | % in some sites the name of the helvetica bold font may differ,
50 | % change the name here:
51 | \font\tenhv = phvb at 10pt
52 | %\font\tenhv = phvb7t at 10pt
53 |
54 | % eleven point times bold required for second-order headings
55 | % \font\elvbf = cmbx10 scaled 1100
56 | \font\elvbf = ptmb scaled 1100
57 |
58 | % set dimensions of columns, gap between columns, and paragraph indent
59 | \setlength{\textheight}{8.875in}
60 | \setlength{\textwidth}{6.875in}
61 | \setlength{\columnsep}{0.3125in}
62 | \setlength{\topmargin}{0in}
63 | \setlength{\headheight}{0in}
64 | \setlength{\headsep}{0in}
65 | \setlength{\parindent}{1pc}
66 | \setlength{\oddsidemargin}{-.304in}
67 | \setlength{\evensidemargin}{-.304in}
68 |
69 | % memento from size10.clo
70 | % \normalsize{\@setfontsize\normalsize\@xpt\@xiipt}
71 | % \small{\@setfontsize\small\@ixpt{11}}
72 | % \footnotesize{\@setfontsize\footnotesize\@viiipt{9.5}}
73 | % \scriptsize{\@setfontsize\scriptsize\@viipt\@viiipt}
74 | % \tiny{\@setfontsize\tiny\@vpt\@vipt}
75 | % \large{\@setfontsize\large\@xiipt{14}}
76 | % \Large{\@setfontsize\Large\@xivpt{18}}
77 | % \LARGE{\@setfontsize\LARGE\@xviipt{22}}
78 | % \huge{\@setfontsize\huge\@xxpt{25}}
79 | % \Huge{\@setfontsize\Huge\@xxvpt{30}}
80 |
81 | \def\@maketitle
82 | {
83 | \newpage
84 | \null
85 | \vskip .375in
86 | \begin{center}
87 | {\Large \bf \@title \par}
88 | % additional two empty lines at the end of the title
89 | \vspace*{24pt}
90 | {
91 | \large
92 | \lineskip .5em
93 | \begin{tabular}[t]{c}
94 | \@author
95 | \end{tabular}
96 | \par
97 | }
98 | % additional small space at the end of the author name
99 | \vskip .5em
100 | {
101 | \large
102 | \begin{tabular}[t]{c}
103 | \@affiliation
104 | \end{tabular}
105 | \par
106 | \ifx \@empty \@email
107 | \else
108 | \begin{tabular}{r@{~}l}
109 | E-mail: & {\tt \@email}
110 | \end{tabular}
111 | \par
112 | \fi
113 | }
114 | % additional empty line at the end of the title block
115 | \vspace*{12pt}
116 | \end{center}
117 | }
118 |
119 | \def\abstract
120 | {%
121 | \centerline{\large\bf Abstract}%
122 | \vspace*{12pt}%
123 | \it%
124 | }
125 |
126 | \def\endabstract
127 | {
128 | % additional empty line at the end of the abstract
129 | \vspace*{12pt}
130 | }
131 |
132 | \def\affiliation#1{\gdef\@affiliation{#1}} \gdef\@affiliation{}
133 |
134 | \def\email#1{\gdef\@email{#1}}
135 | \gdef\@email{}
136 |
137 | \newlength{\@ctmp}
138 | \newlength{\@figindent}
139 | \setlength{\@figindent}{1pc}
140 |
141 | \long\def\@makecaption#1#2{
142 | \vskip 10pt
143 | \setbox\@tempboxa\hbox{\tenhv\noindent #1.~#2}
144 | \setlength{\@ctmp}{\hsize}
145 | \addtolength{\@ctmp}{-\@figindent}\addtolength{\@ctmp}{-\@figindent}
146 | % IF longer than one indented paragraph line
147 | \ifdim \wd\@tempboxa >\@ctmp
148 | % THEN set as an indented paragraph
149 | \begin{list}{}{\leftmargin\@figindent \rightmargin\leftmargin}
150 | \item[]\tenhv #1.~#2\par
151 | \end{list}
152 | \else
153 | % ELSE center
154 | \hbox to\hsize{\hfil\box\@tempboxa\hfil}
155 | \fi}
156 |
157 | % correct heading spacing and type
158 | \def\section{\@startsection {section}{1}{\z@}
159 | {14pt plus 2pt minus 2pt}{14pt plus 2pt minus 2pt} {\large\bf}}
160 | \def\subsection{\@startsection {subsection}{2}{\z@}
161 | {13pt plus 2pt minus 2pt}{13pt plus 2pt minus 2pt} {\elvbf}}
162 |
163 | % add the period after section numbers
164 | \newcommand{\Section}[1]{\section{\hskip -1em.~#1}}
165 | \newcommand{\SubSection}[1]{\subsection{\hskip -1em.~#1}}
166 |
167 | % end of file latex8.sty
168 | % ---------------------------------------------------------------
169 |
--------------------------------------------------------------------------------