You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Feb 23, 2022. It is now read-only.
* wip
* wip
* wip
* remove comments in favor of gh comments
* wip
* udpates to language, should must etc
* Apply suggestions from code review
Co-authored-by: M. J. Fromberger <[email protected]>
* remove tendermint cache description
Co-authored-by: M. J. Fromberger <[email protected]>
Copy file name to clipboardExpand all lines: spec/abci/apps.md
+61-87Lines changed: 61 additions & 87 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,7 +9,7 @@ Please ensure you've first read the spec for [ABCI Methods and Types](abci.md)
9
9
10
10
Here we cover the following components of ABCI applications:
11
11
12
-
-[Connection State](#state) - the interplay between ABCI connections and application state
12
+
-[Connection State](#connection-state) - the interplay between ABCI connections and application state
13
13
and the differences between `CheckTx` and `DeliverTx`.
14
14
-[Transaction Results](#transaction-results) - rules around transaction
15
15
results and validity
@@ -21,7 +21,7 @@ Here we cover the following components of ABCI applications:
21
21
Tendermint and the application on startup.
22
22
-[State Sync](#state-sync) - rapid bootstrapping of new nodes by restoring state machine snapshots
23
23
24
-
## State
24
+
## Connection State
25
25
26
26
Since Tendermint maintains four concurrent ABCI connections, it is typical
27
27
for an application to maintain a distinct state for each, and for the states to
@@ -77,66 +77,48 @@ that's no problem, it just can't be part of the sequential logic of the
77
77
78
78
### Consensus Connection
79
79
80
-
The Consensus Connection should maintain a `DeliverTxState` -
81
-
the working state for block execution. It should be updated by the calls to
82
-
`BeginBlock`, `DeliverTx`, and `EndBlock` during block execution and committed to
83
-
disk as the "latest committed state" during `Commit`.
80
+
The Consensus Connection should maintain a `DeliverTxState` - the working state
81
+
for block execution. It should be updated by the calls to`BeginBlock`, `DeliverTx`,
82
+
and `EndBlock` during block execution and committed to disk as the "latest
83
+
committed state" during `Commit`.
84
84
85
-
Updates made to the DeliverTxState by each method call must be readable by each subsequent method -
85
+
Updates made to the `DeliverTxState` by each method call must be readable by each subsequent method -
86
86
ie. the updates are linearizable.
87
87
88
-
-[BeginBlock](#beginblock)
89
-
-[EndBlock](#endblock)
90
-
-[Deliver Tx](#delivertx)
91
-
-[Commit](#commit)
92
-
93
88
### Mempool Connection
94
89
95
90
The mempool Connection should maintain a `CheckTxState`
96
91
to sequentially process pending transactions in the mempool that have
97
92
not yet been committed. It should be initialized to the latest committed state
98
93
at the end of every `Commit`.
99
94
100
-
The CheckTxState may be updated concurrently with the DeliverTxState, as
101
-
messages may be sent concurrently on the Consensus and Mempool connections. However,
102
-
before calling `Commit`, Tendermint will lock and flush the mempool connection,
103
-
ensuring that all existing CheckTx are responded to and no new ones can
104
-
begin.
105
-
106
-
After `Commit`, CheckTx is run again on all transactions that remain in the
107
-
node's local mempool after filtering those included in the block. To prevent the
108
-
mempool from rechecking all transactions every time a block is committed, set
109
-
the configuration option `mempool.recheck=false`. As of Tendermint v0.32.1,
110
-
an additional `Type` parameter is made available to the CheckTx function that
95
+
Before calling `Commit`, Tendermint will lock and flush the mempool connection,
96
+
ensuring that all existing CheckTx are responded to and no new ones can begin.
97
+
The `CheckTxState` may be updated concurrently with the `DeliverTxState`, as
98
+
messages may be sent concurrently on the Consensus and Mempool connections.
99
+
100
+
After `Commit`, while still holding the mempool lock, CheckTx is run again on all transactions that remain in the
101
+
node's local mempool after filtering those included in the block.
102
+
An additional `Type` parameter is made available to the CheckTx function that
111
103
indicates whether an incoming transaction is new (`CheckTxType_New`), or a
112
104
recheck (`CheckTxType_Recheck`).
113
105
114
-
Finally, the mempool will unlock and new transactions can be processed through CheckTx again.
106
+
Finally, after re-checking transactions in the mempool, Tendermint will unlock
107
+
the mempool connection. New transactions are once again able to be processed through CheckTx.
115
108
116
-
Note that CheckTx doesn't have to check everything that affects transaction validity; the
117
-
expensive things can be skipped. In fact, CheckTx doesn't have to check
118
-
anything; it might say that any transaction is a valid transaction.
119
-
Unlike DeliverTx, CheckTx is just there as
120
-
a sort of weak filter to keep invalid transactions out of the blockchain. It's
121
-
weak, because a Byzantine node doesn't care about CheckTx; it can propose a
122
-
block full of invalid transactions if it wants.
109
+
Note that CheckTx is just a weak filter to keep invalid transactions out of the block chain.
110
+
CheckTx doesn't have to check everything that affects transaction validity; the
111
+
expensive things can be skipped. It's weak because a Byzantine node doesn't
112
+
care about CheckTx; it can propose a block full of invalid transactions if it wants.
123
113
124
114
#### Replay Protection
125
115
126
116
To prevent old transactions from being replayed, CheckTx must implement
127
117
replay protection.
128
118
129
-
Tendermint provides the first defense layer by keeping a lightweight
130
-
in-memory cache of 100k (`[mempool] cache_size`) last transactions in
131
-
the mempool. If Tendermint is just started or the clients sent more than
132
-
100k transactions, old transactions may be sent to the application. So
119
+
It is possible for old transactions to be sent to the application. So
133
120
it is important CheckTx implements some logic to handle them.
134
121
135
-
If there are cases in your application where a transaction may become invalid in some
136
-
future state, you probably want to disable Tendermint's
137
-
cache. You can do that by setting `[mempool] cache_size = 0` in the
138
-
config.
139
-
140
122
### Query Connection
141
123
142
124
The Info Connection should maintain a `QueryState` for answering queries from the user,
@@ -145,8 +127,8 @@ below).
145
127
It should always contain the latest committed state associated with the
146
128
latest committed block.
147
129
148
-
QueryState should be set to the latest `DeliverTxState` at the end of every `Commit`,
149
-
ie. after the full block has been processed and the state committed to disk.
130
+
`QueryState` should be set to the latest `DeliverTxState` at the end of every `Commit`,
131
+
after the full block has been processed and the state committed to disk.
150
132
Otherwise it should never be modified.
151
133
152
134
Tendermint Core currently uses the Query connection to filter peers upon
@@ -165,6 +147,8 @@ Note: these query formats are subject to change!
165
147
The Snapshot Connection is optional, and is only used to serve state sync snapshots for other nodes
166
148
and/or restore state sync snapshots to a local node being bootstrapped.
167
149
150
+
For more information, see [the state sync section of this document](#state-sync).
151
+
168
152
## Transaction Results
169
153
170
154
The `Info` and `Log` fields are non-deterministic values for debugging/convenience purposes
@@ -182,7 +166,7 @@ the difference credited back. Tendermint adopts a similar abstraction,
182
166
though uses it only optionally and weakly, allowing applications to define
183
167
their own sense of the cost of execution.
184
168
185
-
In Tendermint, the `ConsensusParams.Block.MaxGas` limits the amount of `gas` that can be used in a block.
169
+
In Tendermint, the [ConsensusParams.Block.MaxGas](../proto/types/params.proto) limits the amount of `gas` that can be used in a block.
186
170
The default value is `-1`, meaning no limit, or that the concept of gas is
187
171
meaningless.
188
172
@@ -233,7 +217,7 @@ the Tendermint protocol.
233
217
If DeliverTx returns `Code != 0`, the transaction will be considered invalid,
234
218
though it is still included in the block.
235
219
236
-
DeliverTx returns a `abci.Result`, which includes a Code, Data, and Log.
220
+
DeliverTx also returns a [Code, Data, and Log](../../proto/abci/types.proto#L189-L191).
237
221
238
222
`Data` contains the result of the CheckTx transaction execution, if any. It is
239
223
semantically meaningless to Tendermint.
@@ -245,9 +229,9 @@ Both the `Code` and `Data` are included in a structure that is hashed into the
245
229
the transaction by. This allows transactions to be queried according to what
246
230
events took place during their execution.
247
231
248
-
## Validator Updates
232
+
## Updating the Validator Set
249
233
250
-
The application may set the validator set during InitChain, and update it during
234
+
The application may set the validator set during InitChain, and may update it during
251
235
EndBlock.
252
236
253
237
Note that the maximum total power of the validator set is bounded by
@@ -256,16 +240,16 @@ they do not make changes to the validator set that cause it to exceed this
256
240
limit.
257
241
258
242
Additionally, applications must ensure that a single set of updates does not contain any duplicates -
259
-
a given public key can only appear in an update once. If an update includes
243
+
a given public key can only appear once within a given update. If an update includes
260
244
duplicates, the block execution will fail irrecoverably.
261
245
262
246
### InitChain
263
247
264
-
ResponseInitChain can return a list of validators.
248
+
The `InitChain` method can return a list of validators.
265
249
If the list is empty, Tendermint will use the validators loaded in the genesis
266
250
file.
267
-
If the list is not empty, Tendermint will use it for the validator set.
268
-
This way the application can determine the initial validator set for the
251
+
If the list returned by `InitChain`is not empty, Tendermint will use its contents as the validator set.
252
+
This way the application can set the initial validator set for the
269
253
blockchain.
270
254
271
255
### EndBlock
@@ -314,14 +298,14 @@ evidence. They can be set in InitChain and updated in EndBlock.
314
298
The maximum size of a complete Protobuf encoded block.
315
299
This is enforced by Tendermint consensus.
316
300
317
-
This implies a maximum tx size that is this MaxBytes, less the expected size of
301
+
This implies a maximum transaction size that is this MaxBytes, less the expected size of
318
302
the header, the validator set, and any included evidence in the block.
319
303
320
304
Must have `0 < MaxBytes < 100 MB`.
321
305
322
306
### BlockParams.MaxGas
323
307
324
-
The maximum of the sum of `GasWanted` in a proposed block.
308
+
The maximum of the sum of `GasWanted`that will be allowed in a proposed block.
325
309
This is *not* enforced by Tendermint consensus.
326
310
It is left to the app to enforce (ie. if txs are included past the
327
311
limit, they should return non-zero codes). It is used by Tendermint to limit the
@@ -330,15 +314,6 @@ txs included in a proposed block.
330
314
Must have `MaxGas >= -1`.
331
315
If `MaxGas == -1`, no limit is enforced.
332
316
333
-
### BlockParams.TimeIotaMs
334
-
335
-
The minimum time between consecutive blocks (in milliseconds).
336
-
This is enforced by Tendermint consensus.
337
-
338
-
Must have `TimeIotaMs > 0` to ensure time monotonicity.
339
-
340
-
> *Note: This is not exposed to the application*
341
-
342
317
### EvidenceParams.MaxAgeDuration
343
318
344
319
This is the maximum age of evidence in time units.
@@ -368,7 +343,7 @@ This is the maximum number of evidence that can be committed to a single block.
368
343
The product of this and the `MaxEvidenceBytes` must not exceed the size of
369
344
a block minus it's overhead ( ~ `MaxBytes`).
370
345
371
-
The amount must be a positive number.
346
+
Must have `MaxNum > 0`.
372
347
373
348
### Updates
374
349
@@ -382,16 +357,16 @@ value to be updated to 0.
382
357
#### InitChain
383
358
384
359
ResponseInitChain includes a ConsensusParams.
385
-
If its nil, Tendermint will use the params loaded in the genesis
386
-
file. If it's not nil, Tendermint will use it.
360
+
If ConsensusParams is nil, Tendermint will use the params loaded in the genesis
361
+
file. If ConsensusParams is not nil, Tendermint will use it.
387
362
This way the application can determine the initial consensus params for the
388
363
blockchain.
389
364
390
365
#### EndBlock
391
366
392
367
ResponseEndBlock includes a ConsensusParams.
393
-
If its nil, Tendermint will do nothing.
394
-
If it's not nil, Tendermint will use it.
368
+
If ConsensusParams nil, Tendermint will do nothing.
369
+
If ConsensusParam is not nil, Tendermint will use it.
395
370
This way the application can update the consensus params over time.
396
371
397
372
Note the updates returned in block `H` will take effect right away for block
@@ -433,8 +408,7 @@ ABCI applications can take advantage of more efficient light-client proofs for
433
408
their state as follows:
434
409
435
410
- return the Merkle root of the deterministic application state in
436
-
`ResponseCommit.Data`.
437
-
- it will be included as the `AppHash` in the next block.
411
+
`ResponseCommit.Data`. This Merkle root will be included as the `AppHash` in the next block.
438
412
- return efficient Merkle proofs about that application state in `ResponseQuery.Proof`
439
413
that can be verified using the `AppHash` of the corresponding block.
440
414
@@ -494,7 +468,7 @@ On startup, Tendermint calls the `Info` method on the Info Connection to get the
494
468
committed state of the app. The app MUST return information consistent with the
495
469
last block it succesfully completed Commit for.
496
470
497
-
If the app succesfully committed block H but not H+1, then `last_block_height = H` and `last_block_app_hash = <hash returned by Commit for block H>`. If the app
471
+
If the app succesfully committed block H, then `last_block_height = H` and `last_block_app_hash = <hash returned by Commit for block H>`. If the app
498
472
failed during the Commit of block H, then `last_block_height = H-1` and
499
473
`last_block_app_hash = <hash returned by Commit for block H-1, which is the hash in the header of block H>`.
500
474
@@ -507,10 +481,11 @@ stateBlockHeight = height of the last block for which Tendermint completed all
507
481
block processing and saved all ABCI results to disk
508
482
appBlockHeight = height of the last block for which ABCI app succesfully
509
483
completed Commit
484
+
510
485
```
511
486
512
487
Note we always have `storeBlockHeight >= stateBlockHeight` and `storeBlockHeight >= appBlockHeight`
513
-
Note also we never call Commit on an ABCI app twice for the same height.
488
+
Note also Tendermint never calls Commit on an ABCI app twice for the same height.
514
489
515
490
The procedure is as follows.
516
491
@@ -595,19 +570,19 @@ sent across the network, snapshot metadata messages are limited to 4 MB.
595
570
When a new node is running state sync and discovering snapshots, Tendermint will query an existing
596
571
application via the ABCI `ListSnapshots` method to discover available snapshots, and load binary
597
572
snapshot chunks via `LoadSnapshotChunk`. The application is free to choose how to implement this
598
-
and which formats to use, but should provide the following guarantees:
573
+
and which formats to use, but must provide the following guarantees:
599
574
600
-
-**Consistent:** A snapshot should be taken at a single isolated height, unaffected by
601
-
concurrent writes. This can e.g. be accomplished by using a data store that supports ACID
575
+
-**Consistent:** A snapshot must be taken at a single isolated height, unaffected by
576
+
concurrent writes. This can be accomplished by using a data store that supports ACID
602
577
transactions with snapshot isolation.
603
578
604
-
-**Asynchronous:** Taking a snapshot can be time-consuming, so it should not halt chain progress,
579
+
-**Asynchronous:** Taking a snapshot can be time-consuming, so it must not halt chain progress,
605
580
for example by running in a separate thread.
606
581
607
-
-**Deterministic:** A snapshot taken at the same height in the same format should be identical
582
+
-**Deterministic:** A snapshot taken at the same height in the same format must be identical
608
583
(at the byte level) across nodes, including all metadata. This ensures good availability of
609
584
chunks, and that they fit together across nodes.
610
-
585
+
611
586
A very basic approach might be to use a datastore with MVCC transactions (such as RocksDB),
612
587
start a transaction immediately after block commit, and spawn a new thread which is passed the
613
588
transaction handle. This thread can then export all data items, serialize them using e.g.
@@ -629,10 +604,10 @@ trusted header hash and corresponding height from a trusted source, via the `sta
629
604
configuration section.
630
605
631
606
Once started, the node will connect to the P2P network and begin discovering snapshots. These
632
-
will be offered to the local application, and once a snapshot is accepted Tendermint will fetch
633
-
and apply the snapshot chunks. After all chunks have been successfully applied, Tendermint verifies
634
-
the app's `AppHash` against the chain using the light client, then switches the node to normal
635
-
consensus operation.
607
+
will be offered to the local application via the `OfferSnapshot` ABCI method. Once a snapshot
608
+
is accepted Tendermint will fetch and apply the snapshot chunks. After all chunks have been
609
+
successfully applied, Tendermint verifies the app's `AppHash` against the chain using the light
610
+
client, then switches the node to normal consensus operation.
636
611
637
612
#### Snapshot Discovery
638
613
@@ -651,8 +626,7 @@ any peers that have the same snapshot (i.e. that have identical metadata fields)
651
626
spooled in a temporary directory, and then given to the application in sequential order via
652
627
`ApplySnapshotChunk` until all chunks have been accepted.
653
628
654
-
As with taking snapshots, the method for restoring them is entirely up to the application, but will
655
-
generally be the inverse of how they are taken.
629
+
The method for restoring snapshot chunks is entirely up to the application.
656
630
657
631
During restoration, the application can respond to `ApplySnapshotChunk` with instructions for how
658
632
to continue. This will typically be to accept the chunk and await the next one, but it can also
@@ -686,12 +660,12 @@ P2P configuration options to whitelist a set of trusted peers that can provide v
686
660
687
661
#### Transition to Consensus
688
662
689
-
Once the snapshot has been restored, Tendermint gathers additional information necessary for
663
+
Once the snapshots have all been restored, Tendermint gathers additional information necessary for
690
664
bootstrapping the node (e.g. chain ID, consensus parameters, validator sets, and block headers)
691
665
from the genesis file and light client RPC servers. It also fetches and records the `AppVersion`
692
666
from the ABCI application.
693
667
694
-
Once the node is bootstrapped with this information and the restored state machine, it transitions
695
-
to fast sync (if enabled) to fetch any remaining blocks up the the chain head, and then
696
-
transitions to regular consensus operation. At this point the node operates like any other node,
697
-
apart from having a truncated block history at the height of the restored snapshot.
668
+
Once the state machine has been restored and Tendermint has gathered this additional
669
+
information, it transitions to block sync (if enabled) to fetch any remaining blocks up the chain
670
+
head, and then transitions to regular consensus operation. At this point the node operates like
671
+
any other node, apart from having a truncated block history at the height of the restored snapshot.
0 commit comments