Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- `[config]` Move `timeout_commit` into the ABCI `FinalizeBlockResponse`
([\#2655](https://github.com/cometbft/cometbft/issues/2655))
4 changes: 3 additions & 1 deletion abci/types/application.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package types

import "context"
import (
"context"
)

//go:generate ../../scripts/mockery_generate.sh Application

Expand Down
455 changes: 256 additions & 199 deletions abci/types/types.pb.go

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,12 @@ func (cfg *Config) ValidateBasic() error {
return nil
}

// CheckDeprecated returns any deprecation warnings. These are printed to the operator on startup
// CheckDeprecated returns any deprecation warnings. These are printed to the operator on startup.
func (cfg *Config) CheckDeprecated() []string {
var warnings []string
if cfg.Consensus.TimeoutCommit != 0 {
warnings = append(warnings, "[consensus.timeout_commit] is deprecated. Use `next_block_delay` in the ABCI `FinalizeBlockResponse`.")
}
return warnings
}

Expand Down Expand Up @@ -1079,6 +1082,7 @@ func (cfg *ConsensusConfig) Precommit(round int32) time.Duration {

// Commit returns the amount of time to wait for straggler votes after receiving +2/3 precommits
// for a single block (ie. a commit).
// Deprecated: use `next_block_delay` in the ABCI application's `FinalizeBlockResponse`.
func (cfg *ConsensusConfig) Commit(t time.Time) time.Time {
return t.Add(cfg.TimeoutCommit)
}
Expand Down
25 changes: 16 additions & 9 deletions consensus/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -719,15 +719,20 @@ func (cs *State) updateToState(state sm.State) {
cs.updateHeight(height)
cs.updateRoundStep(0, cstypes.RoundStepNewHeight)

timeoutCommit := state.NextBlockDelay
// If the ABCI app didn't set a delay, use the deprecated config value.
if timeoutCommit == 0 {
timeoutCommit = cs.config.TimeoutCommit //nolint:staticcheck
}
if cs.CommitTime.IsZero() {
// "Now" makes it easier to sync up dev nodes.
// We add timeoutCommit to allow transactions
// to be gathered for the first block.
// And alternative solution that relies on clocks:
// cs.StartTime = state.LastBlockTime.Add(timeoutCommit)
cs.StartTime = cs.config.Commit(cmttime.Now())
//
// We add timeoutCommit to allow transactions to be gathered for
// the first block. An alternative solution that relies on clocks:
// `cs.StartTime = state.LastBlockTime.Add(timeoutCommit)`
cs.StartTime = cmttime.Now().Add(timeoutCommit)
} else {
cs.StartTime = cs.config.Commit(cs.CommitTime)
cs.StartTime = cs.CommitTime.Add(timeoutCommit)
}

cs.Validators = validators
Expand Down Expand Up @@ -1043,7 +1048,7 @@ func (cs *State) handleTxsAvailable() {

// Enter: `timeoutNewHeight` by startTime (commitTime+timeoutCommit),
//
// or, if SkipTimeoutCommit==true, after receiving all precommits from (height,round-1)
// or, if NextBlockDelay==0, after receiving all precommits from (height,round-1)
//
// Enter: `timeoutPrecommits` after any +2/3 precommits from (height,round-1)
// Enter: +2/3 precommits for nil at (height,round-1)
Expand Down Expand Up @@ -2155,7 +2160,8 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error
cs.evsw.FireEvent(types.EventVote, vote)

// if we can skip timeoutCommit and have all the votes now,
if cs.config.SkipTimeoutCommit && cs.LastCommit.HasAll() {
skipTimeoutCommit := cs.state.NextBlockDelay == 0 && cs.config.TimeoutCommit == 0 //nolint:staticcheck
if skipTimeoutCommit && cs.LastCommit.HasAll() {
// go straight to new round (skip timeout commit)
// cs.scheduleTimeout(time.Duration(0), cs.Height, 0, cstypes.RoundStepNewHeight)
cs.enterNewRound(cs.Height, 0)
Expand Down Expand Up @@ -2333,7 +2339,8 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error

if len(blockID.Hash) != 0 {
cs.enterCommit(height, vote.Round)
if cs.config.SkipTimeoutCommit && precommits.HasAll() {
skipTimeoutCommit := cs.state.NextBlockDelay == 0 && cs.config.TimeoutCommit == 0 //nolint:staticcheck
if skipTimeoutCommit && precommits.HasAll() {
cs.enterNewRound(cs.Height, 0)
}
} else {
Expand Down
110 changes: 51 additions & 59 deletions docs/app-dev/indexing-transactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ transferBalance200FinalizeBlock12 1
transferNodeNothingFinalizeBlock12 1

```

The event number is a local variable kept by the indexer and incremented when a new event is processed.
It is an `int64` variable and has no other semantics besides being used to associate attributes belonging to the same events within a height.
This variable is not atomically incremented as event indexing is deterministic. **Should this ever change**, the event id generation
Expand Down Expand Up @@ -173,51 +172,50 @@ UTF-8 encoded strings (e.g. "transfer.sender": "Bob", "transfer.recipient":
Example:

```go
func (app *Application) FinalizeBlock(_ context.Context, req *types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error) {

func (app *Application) FinalizeBlock(_ context.Context, req *types.FinalizeBlockRequest) (*types.FinalizeBlockResponse, error) {
//...
tx_results[0] := &types.ExecTxResult{
Code: CodeTypeOK,
// With every transaction we can emit a series of events. To make it simple, we just emit the same events.
Events: []types.Event{
{
Type: "app",
Attributes: []types.EventAttribute{
{Key: "creator", Value: "Cosmoshi Netowoko", Index: true},
{Key: "key", Value: key, Index: true},
{Key: "index_key", Value: "index is working", Index: true},
{Key: "noindex_key", Value: "index is working", Index: false},
},
},
{
Type: "app",
Attributes: []types.EventAttribute{
{Key: "creator", Value: "Cosmoshi", Index: true},
{Key: "key", Value: value, Index: true},
{Key: "index_key", Value: "index is working", Index: true},
{Key: "noindex_key", Value: "index is working", Index: false},
},
},
},
}
tx_results[0] := &types.ExecTxResult{
Code: CodeTypeOK,
// With every transaction we can emit a series of events. To make it simple, we just emit the same events.
Events: []types.Event{
{
Type: "app",
Attributes: []types.EventAttribute{
{Key: "creator", Value: "Cosmoshi Netowoko", Index: true},
{Key: "key", Value: key, Index: true},
{Key: "index_key", Value: "index is working", Index: true},
{Key: "noindex_key", Value: "index is working", Index: false},
},
},
{
Type: "app",
Attributes: []types.EventAttribute{
{Key: "creator", Value: "Cosmoshi", Index: true},
{Key: "key", Value: value, Index: true},
{Key: "index_key", Value: "index is working", Index: true},
{Key: "noindex_key", Value: "index is working", Index: false},
},
},
},
}

block_events = []types.Event{
{
Type: "loan",
Attributes: []types.EventAttribute{
{ Key: "account_no", Value: "1", Index: true},
{ Key: "amount", Value: "200", Index: true },
},
},
{
Type: "loan",
Attributes: []types.EventAttribute{
{ Key: "account_no", Value: "2", Index: true },
{ Key: "amount", Value: "300", Index: true},
},
},
}
return &types.ResponseFinalizeBlock{TxResults: tx_results, Events: block_events}
{
Type: "loan",
Attributes: []types.EventAttribute{
{Key: "account_no", Value: "1", Index: true},
{Key: "amount", Value: "200", Index: true},
},
},
{
Type: "loan",
Attributes: []types.EventAttribute{
{Key: "account_no", Value: "2", Index: true},
{Key: "amount", Value: "300", Index: true},
},
},
}
return &types.FinalizeBlockResponse{TxResults: tx_results, Events: block_events, NextBlockDelay: 1 * time.Second}, nil
}
```

Expand Down Expand Up @@ -266,30 +264,24 @@ curl "localhost:26657/block_search?query=\"block.height > 10\""
```


Storing the event sequence was introduced in CometBFT 0.34.26. Before that, up
until Tendermint Core 0.34.26, the event sequence was not stored in the kvstore
and events were stored only by height. That means that queries returned blocks
and transactions whose event attributes match within the height but can match
across different events on that height.

This behavior was fixed with CometBFT 0.34.26+. However, if the data was
indexed with earlier versions of Tendermint Core and not re-indexed, that data
will be queried as if all the attributes within a height occurred within the
same event.
Storing the event sequence was introduced in CometBFT 0.34.26. Before that, up until Tendermint Core 0.34.26,
the event sequence was not stored in the kvstore and events were stored only by height. That means that queries
returned blocks and transactions whose event attributes match within the height but can match across different
events on that height.
This behavior was fixed with CometBFT 0.34.26+. However, if the data was indexed with earlier versions of
Tendermint Core and not re-indexed, that data will be queried as if all the attributes within a height
occurred within the same event.

## Event attribute value types

Users can use anything as an event value. However, if the event attribute value
is a number, the following needs to be taken into account:

- Negative numbers will not be properly retrieved when querying the indexer.
- Event values are converted to big floats (from the `big/math` package). The
precision of the floating point number is set to the bit length of the
integer it is supposed to represent, so that there is no loss of information
due to insufficient precision. This was not present before CometBFT v0.38.x
and all float values were ignored.
- Event values are converted to big floats (from the `big/math` package). The precision of the floating point number is set to the bit length
of the integer it is supposed to represent, so that there is no loss of information due to insufficient precision. This was not present before CometBFT v0.38.x and all float values were ignored.
- As of CometBFT v0.38.x, queries can contain floating point numbers as well.
- Note that comparing to floats can be imprecise with a high number of decimals.
- Note that comparing to floats can be imprecise with a high number of decimals.

## Event type and attribute key format

Expand Down
1 change: 1 addition & 0 deletions docs/core/using-cometbft.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ definition](https://github.com/cometbft/cometbft/blob/v0.38.x/types/genesis.go))
"consensus_params": {
"block": {
"max_bytes": "22020096",
"block_time": "2000000000",
"max_gas": "-1",
},
"evidence": {
Expand Down
3 changes: 3 additions & 0 deletions docs/guides/go-built-in.md
Original file line number Diff line number Diff line change
Expand Up @@ -375,10 +375,13 @@ func (app *KVStoreApplication) FinalizeBlock(_ context.Context, req *abcitypes.R

return &abcitypes.ResponseFinalizeBlock{
TxResults: txs,
NextBlockDelay: 1 * time.Second,
}, nil
}
```

`NextBlockDelay` is a delay between the time when the current block is committed and the next height is started. Normally you don't need to change the default value (1s). Please refer to the [spec](../../spec/abci/abci++_methods.md#finalizeblock) for more information.

Transactions are not guaranteed to be valid when they are delivered to an application, even if they were valid when they were proposed.

This can happen if the application state is used to determine transaction validity.
Expand Down
7 changes: 5 additions & 2 deletions docs/guides/go.md
Original file line number Diff line number Diff line change
Expand Up @@ -373,12 +373,15 @@ func (app *KVStoreApplication) FinalizeBlock(_ context.Context, req *abcitypes.R
}
}

return &abcitypes.ResponseFinalizeBlock{
TxResults: txs,
return &abcitypes.FinalizeBlockResponse{
TxResults: txs,
NextBlockDelay: 1 * time.Second,
}, nil
}
```

`NextBlockDelay` is a delay between the time when the current block is committed and the next height is started. Normally you don't need to change the default value (1s). Please refer to the [spec](../../spec/abci/abci++_methods.md#finalizeblock) for more information.

Transactions are not guaranteed to be valid when they are delivered to an application, even if they were valid when they were proposed.

This can happen if the application state is used to determine transaction validity. The application state may have changed between the initial execution of `CheckTx` and the transaction delivery in `FinalizeBlock` in a way that rendered the transaction no longer valid.
Expand Down
2 changes: 1 addition & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/moricho/tparallel v0.3.0 h1:8dDx3S3e+jA+xiQXC7O3dvfRTe/J+FYlTDDW01Y7z/Q=
github.com/moricho/tparallel v0.3.0 h1:EthKzLoZA6C11YB1vMPWLYmF2nnPCUX712TjDgsP31A=
github.com/moricho/tparallel v0.3.0/go.mod h1:leENX2cUv7Sv2qDgdi0D0fCftN8fRC67Bcn8pqzeYNI=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
Expand Down
1 change: 1 addition & 0 deletions internal/test/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ var testGenesisFmt = `{
"block": {
"max_bytes": "22020096",
"max_gas": "-1",
"block_time": "2000000000",
"time_iota_ms": "10"
},
"evidence": {
Expand Down
7 changes: 7 additions & 0 deletions proto/tendermint/abci/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import "tendermint/crypto/keys.proto";
import "tendermint/types/params.proto";
import "tendermint/types/validator.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
import "gogoproto/gogo.proto";

// NOTE: When using custom types, mind the warnings.
Expand Down Expand Up @@ -363,6 +364,12 @@ message ResponseFinalizeBlock {
tendermint.types.ConsensusParams consensus_param_updates = 4;
// app_hash is the hash of the applications' state which is used to confirm that execution of the transactions was deterministic. It is up to the application to decide which algorithm to use.
bytes app_hash = 5;
// delay between the time when this block is committed and the next height is started.
// previously `timeout_commit` in config.toml
google.protobuf.Duration next_block_delay = 6 [
(gogoproto.nullable) = false,
(gogoproto.stdduration) = true
];
}

//----------------------------------------
Expand Down
Loading
Loading