mirror of
https://github.com/fluencelabs/tendermint-demo
synced 2025-03-14 15:20:50 +00:00
Housekeeping
This commit is contained in:
parent
e0f66f18ea
commit
b06c2fc5b2
121
README.md
121
README.md
@ -30,12 +30,6 @@ Because every computation is verified by the cluster nodes and computation outco
|
||||
* [Client implementation details](#client-implementation-details)
|
||||
* [Transactions and Merkle hashes](#transactions-and-merkle-hashes)
|
||||
* [Problematic situations review ](#problematic-situations-review)
|
||||
* [A. Cases which the client can detect and handle](#a-cases-which-the-client-can-detect-and-handle)
|
||||
* [B. Cases which the client can detect, but cannot handle](#b-cases-which-the-client-can-detect-but-cannot-handle)
|
||||
* [C. Dispute cases](#c-dispute-cases)
|
||||
* [C1. Some nodes correct, some not, no quorum](#dispute-case-c1-some-nodes-correct-some-not-no-quorum)
|
||||
* [C2. Byzantine quorum, minority of correct nodes](#dispute-case-c2-byzantine-quorum-minority-of-correct-nodes)
|
||||
* [C3. Correct quorum, some nodes Byzantine or not available](#dispute-case-c3-correct-quorum-some-nodes-byzantine-or-not-available)
|
||||
|
||||
## Motivation
|
||||
The application is a proof-of-concept of a decentralized system with the following properties:
|
||||
@ -335,118 +329,3 @@ There is a number of situations which might potentially go wrong with this demo
|
||||
|
||||
* If there are too many Byzantine nodes, consensus over the incorrect state transition might be reached. If there is at least one honest node in the cluster, it might escalate a dispute to the Judge (unless it was excluded from the cluster communication by colluding Byzantine nodes).
|
||||
|
||||
### C. Dispute cases
|
||||
Dispute cases, in general, cannot be detected by the client, because the client is normally satisfied by the first successful response while retrying response to the cluster nodes. The external Judge is available to the correct nodes in order to prevent such situations (instead of multicasting the client requests to all cluster nodes and comparing the responses).
|
||||
|
||||
Another, even more important, reason is that the dispute case might violate the cluster **safety**! When there is a *Byzantine quorum*, Byzantine nodes might provide to the client as wrong responses as they want, but the client keeps trusting the cluster because no Cases B and even Cases A evidence is observed. So the external Judge should also be able to replay the computations that caused the dispute.
|
||||
|
||||
#### Dispute case C1: some nodes correct, some not, no quorum
|
||||
When the last block is `height`-th and there is no quorum (neither correct nor Byzantine) for `height+1`-th block's voting, liveness is violated and new blocks cannot be formed. Such situation might happen if the cluster cannot reach an agreement about next block. Even if TM Core works as expected, different State machines on different nodes might provide to local TM Cores different app hashes for `height`-th block. As already said, Case B2 is usually an aftermath of this case.
|
||||
|
||||
To simulate disputes in the local cluster the special key `wrong` might be used. If some node's State machine (indexed 1 to 4 which corresponds to their ports `46158`, `46258`, `46358`, `46458`) get `put` request targeted to `wrong` and a provided value contains node's index, it prepends a prefix `wrong` to this value. For example, after `put wrong=13` request, the 2nd and 4th nodes map `wrong` to `13`, but 1st and 2rd nodes map it to `wrong13`. Consequently, those 'wrong' nodes obtain 'wrong' `app_hash` which disputes with correct `app_hash`.
|
||||
|
||||
This convention works well to illustrate Dispute case C1. First, let's try using `fastput`, an unchecked alternative to `put` (it does not wait for the next block with the current block's `app_hash`) to submit new `wrong` value:
|
||||
```bash
|
||||
> python query.py localhost:46157 fastput -v wrong=34
|
||||
HEIGHT: 3
|
||||
INFO: 34
|
||||
OK
|
||||
```
|
||||
This invocation return info `34` and `OK` status. At first glance, everything is well because `height`-th (the 3rd actually) block formed and `INFO` equal to new value `34` got. However, this `INFO` should be considered as *tentative* because despite successful the 3rd block formation it's needed to wait for the 4th block that should contain `app_hash` for 3rd block. Note that the source of `INFO` is just output of `DeliverTx` from single App and this output is neither merkelized nor signed by other nodes.
|
||||
|
||||
Now the blockchain has inconsistent state. Let's reset it via `local-cluster-reset.sh`, wait some time for cluster initialization and instead of unchecked `fastput` use checked `put`:
|
||||
```bash
|
||||
> python query.py localhost:46157 put -v wrong=34
|
||||
HEIGHT: 3
|
||||
APP_HASH: NOT_READY
|
||||
PROOF: NO_PROOF
|
||||
RESULT: EMPTY
|
||||
BAD: Cannot verify tentative '34'! Height is not verifiable
|
||||
```
|
||||
`put` waits for `height+1`-th block before responding. As before, 3rd block formation is successful but it's not enough for `put`, it waits for 4th block. After some timeout, it responds that this block is still not available, so tentative `34` value is not confirmed.
|
||||
|
||||
The State machine itself also monitors block creation. The Monitor thread of the App that checks the following condition periodically: if 1 second elapsed from last non-empty block in the blockchain there must be an empty block after that block. In case this does not hold, the Monitors detects a dispute and signals the Judge that cluster needs to be fixed. Of course, the timeout value (default is 1 second) is configurable. This might be checked by querying the Judge status:
|
||||
```bash
|
||||
> curl -s "localhost:8080/status" | jq
|
||||
{
|
||||
"1": {
|
||||
"status": "No quorum",
|
||||
"app_hash": "366D393BAD6563C067CBF8F7CF582EB7FE61217C8FC0264903789E307FC95EFB",
|
||||
"height": 3
|
||||
},
|
||||
"3": {
|
||||
"status": "No quorum",
|
||||
"app_hash": "A35CF646E011DCBA103705B1BCA2AB196AE8FA1F46A662E086A33C6DD518CC22",
|
||||
"height": 3
|
||||
},
|
||||
"2": {
|
||||
"status": "No quorum",
|
||||
"app_hash": "366D393BAD6563C067CBF8F7CF582EB7FE61217C8FC0264903789E307FC95EFB",
|
||||
"height": 3
|
||||
},
|
||||
"4": {
|
||||
"status": "No quorum",
|
||||
"app_hash": "A35CF646E011DCBA103705B1BCA2AB196AE8FA1F46A662E086A33C6DD518CC22",
|
||||
"height": 3
|
||||
}
|
||||
}
|
||||
```
|
||||
Here it might be noticed that every node detects the absence of quorum and provides its own version of `app_hash`. Half of the nodes have the correct `app_hash` whereas the rest of nodes has a wrong one.
|
||||
|
||||
#### Dispute case C2: Byzantine quorum, minority of correct nodes
|
||||
This case can also be illustrated using `wrong` key:
|
||||
```bash
|
||||
> python query.py localhost:46157 put -v wrong=123
|
||||
HEIGHT: 3
|
||||
APP_HASH: 3E5B81D6C436A5319577637A005FDA99EAA632C360ACA23AE9BB3BD3766CFE02
|
||||
PROOF: A7FFC6F8BF1ED76651C14756A061D662F580FF4DE43B49FA82D80A4B80F8434A 1AACEE49E178FF7836873CB0D520C5C7D82B772D28997A0EE51A837A5AA5683C 672896E0A9F15E323B6D2166A520701F8423198E0AB3D33415F7E2A844D18454, 10A1E4BF410C6BFD3455EF467700B24842ABE6F9ED6D24C816741F43A8FA8D58
|
||||
RESULT: wrong123
|
||||
OK
|
||||
```
|
||||
|
||||
The 'wrong' nodes (1st, 2nd, and 3rd) have a quorum (despite the 4th disagrees with them) and provide their version of state and corresponding `app_hash`. The Client validates the blockchain information and provided response and treats it correct. From the Client's point of view it is impossible in general case to discriminate a correct response and a falsified response in presence of a Byzantine quorum.
|
||||
|
||||
This example is pretty artificial because the trivial comparison of the target value `123` with the result `wrong123` might be done. However, in case of a non-trivial operation the client is unable to reproduce an arbitrary computation and cannot detect the incorrect response.
|
||||
|
||||
Node 4 is able to detect the disagreement, which might be checked via the Judge status
|
||||
```bash
|
||||
> curl -s "localhost:8080/status" | jq
|
||||
{
|
||||
"1": {
|
||||
"status": "OK",
|
||||
"app_hash": "3E5B81D6C436A5319577637A005FDA99EAA632C360ACA23AE9BB3BD3766CFE02",
|
||||
"height": 4
|
||||
},
|
||||
"3": {
|
||||
"status": "OK",
|
||||
"app_hash": "3E5B81D6C436A5319577637A005FDA99EAA632C360ACA23AE9BB3BD3766CFE02",
|
||||
"height": 4
|
||||
},
|
||||
"2": {
|
||||
"status": "OK",
|
||||
"app_hash": "3E5B81D6C436A5319577637A005FDA99EAA632C360ACA23AE9BB3BD3766CFE02",
|
||||
"height": 4
|
||||
},
|
||||
"4": {
|
||||
"status": "Disagreement with quorum",
|
||||
"app_hash": "431ED90111F3A4D5349DF955B664CA63950CB768526DD9F5105C26A3723CBB53",
|
||||
"height": 3
|
||||
}
|
||||
}
|
||||
```
|
||||
To achieve this detection the State machine Monitor periodically requests its peer's TM Core RPC's for the next block and compares their `app_hash`-es with its own `app_hash`. In case of a disagreement the Monitor immediately raises the dispute to the Judge.
|
||||
|
||||
#### Dispute case C3: correct quorum, some nodes Byzantine or not available
|
||||
This case is symmetric to the previous, but the quorum is correct now.
|
||||
|
||||
When a quorum (2/3+ nodes of the cluster) exists, the availability of other nodes does not influence cluster's safety or liveness. This demo app does not implement any special checks for the existence of nodes absent or Byzantine during operation processing. Let's illustrate this using `wrong` key:
|
||||
```bash
|
||||
> python query.py localhost:46157 put -v wrong=4
|
||||
HEIGHT: 3
|
||||
APP_HASH: 7B840A448231110FC3746EE06C0053E6EADE213189BDFDB902E7FBA6A486643B
|
||||
PROOF: A7FFC6F8BF1ED76651C14756A061D662F580FF4DE43B49FA82D80A4B80F8434A 1AACEE49E178FF7836873CB0D520C5C7D82B772D28997A0EE51A837A5AA5683C B103DC8A5244FD6548F7C0DE617EE66D25F79007A993BC15C6EA11D8390E6279, B410677B84ED73FAC43FCF1ABD933151DD417D932A0EF9B0260ECF8B7B72ECB9
|
||||
RESULT: 4
|
||||
OK
|
||||
```
|
||||
|
||||
Here the 4th Node is 'wrong'. It detects a disagreement and might raise the dispute to the Judge. But in this case the Judge would detect this Node as incorrect and punish it.
|
||||
|
Loading…
x
Reference in New Issue
Block a user