Skip to content
Open
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
6 changes: 3 additions & 3 deletions docs/build/abci/03-vote-extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ ABCI 2.0 (colloquially called ABCI++) allows an application to extend a pre-comm
validator process. The Cosmos SDK defines [`baseapp.ExtendVoteHandler`](https://github.com/cosmos/cosmos-sdk/blob/v0.53.0/types/abci.go#L32):

```go
type ExtendVoteHandler func(Context, *abci.ExtendVoteRequest) (*abci.ExtendVoteResponse, error)
type ExtendVoteHandler func(Context, *abci.RequestExtendVote) (*abci.ResponseExtendVote, error)
```

An application can set this handler in `app.go` via the `baseapp.SetExtendVoteHandler`
Expand All @@ -38,7 +38,7 @@ other validators when validating their pre-commits. For a given vote extension,
this process MUST be deterministic. The Cosmos SDK defines [`sdk.VerifyVoteExtensionHandler`](https://github.com/cosmos/cosmos-sdk/blob/v0.50.1/types/abci.go#L29-L31):

```go
type VerifyVoteExtensionHandler func(Context, *abci.VerifyVoteExtensionRequest) (*abci.VerifyVoteExtensionResponse, error)
type VerifyVoteExtensionHandler func(Context, *abci.RequestVerifyVoteExtension) (*abci.ResponseVerifyVoteExtension, error)
```

An application can set this handler in `app.go` via the `baseapp.SetVerifyVoteExtensionHandler`
Expand Down Expand Up @@ -78,7 +78,7 @@ will be available to the application during the subsequent `FinalizeBlock` call.
An example of how a pre-FinalizeBlock hook could look like is shown below:

```go
app.SetPreBlocker(func(ctx sdk.Context, req *abci.FinalizeBlockRequest) error {
app.SetPreBlocker(func(ctx sdk.Context, req *abci.RequestFinalizeBlock) error {
allVEs := []VE{} // store all parsed vote extensions here
for _, tx := range req.Txs {
// define a custom function that tries to parse the tx as a vote extension
Expand Down
2 changes: 1 addition & 1 deletion docs/build/architecture/adr-030-authz-module.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ The concrete use cases which motivated this module include:
delegated stake
* "sub-keys" functionality, as originally proposed in [\#4480](https://github.com/cosmos/cosmos-sdk/issues/4480) which
is a term used to describe the functionality provided by this module together with
the `fee_grant` module from [ADR 029](./adr-029-fee-grant-module.md) and the [group module](https://github.com/cosmos/cosmos-sdk/tree/main/x/group).
the `fee_grant` module from [ADR 029](./adr-029-fee-grant-module.md) and the [group module](https://github.com/cosmos/cosmos-sdk/tree/main/contrib/x/group).

The "sub-keys" functionality roughly refers to the ability for one account to grant some subset of its capabilities to
other accounts with possibly less robust, but easier to use security measures. For instance, a master account representing
Expand Down
38 changes: 19 additions & 19 deletions docs/build/architecture/adr-038-state-listening.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* 10/14/2022:
* Add `ListenCommit`, flatten the state writes in a block to a single batch.
* Remove listeners from cache stores, should only listen to `rootmulti.Store`.
* Remove `HaltAppOnDeliveryError()`, the errors are propagated by default, the implementations should return nil if they don't want to propagate errors.
* Remove `HaltAppOnDeliveryError()`, the errors are propagated by default, the implementations should return nil if don't want to propagate errors.
* 26/05/2023: Update with ABCI 2.0

## Status
Expand All @@ -20,7 +20,7 @@ This ADR defines a set of changes to enable listening to state changes of indivi

## Context

Currently, KVStore data can be remotely accessed through [Queries](https://docs.cosmos.network/main/build/building-modules/messages-and-queries#queries)
Currently, KVStore data can be remotely accessed through [Queries](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/messages-and-queries.md#queries)
which proceed either through Tendermint and the ABCI, or through the gRPC server.
In addition to these request/response queries, it would be beneficial to have a means of listening to state changes as they occur in real time.

Expand All @@ -40,7 +40,7 @@ type MemoryListener struct {
stateCache []StoreKVPair
}

// NewMemoryListener creates a listener that accumulates the state writes in memory.
// NewMemoryListener creates a listener that accumulate the state writes in memory.
func NewMemoryListener() *MemoryListener {
return &MemoryListener{}
}
Expand Down Expand Up @@ -114,7 +114,7 @@ func (s *Store) Delete(key []byte) {

### MultiStore interface updates

We will update the `CommitMultiStore` interface to allow us to wrap a `MemoryListener` to a specific `KVStore`.
We will update the `CommitMultiStore` interface to allow us to wrap a `Memorylistener` to a specific `KVStore`.
Note that the `MemoryListener` will be attached internally by the concrete `rootmulti` implementation.

```go
Expand Down Expand Up @@ -224,9 +224,9 @@ so that the service can group the state changes with the ABCI requests.
// ABCIListener is the interface that we're exposing as a streaming service.
type ABCIListener interface {
// ListenFinalizeBlock updates the streaming service with the latest FinalizeBlock messages
ListenFinalizeBlock(ctx context.Context, req abci.FinalizeBlockRequest, res abci.FinalizeBlockResponse) error
// ListenCommit updates the streaming service with the latest Commit messages and state changes
ListenCommit(ctx context.Context, res abci.CommitResponse, changeSet []*StoreKVPair) error
ListenFinalizeBlock(ctx context.Context, req abci.RequestFinalizeBlock, res abci.ResponseFinalizeBlock) error
// ListenCommit updates the steaming service with the latest Commit messages and state changes
ListenCommit(ctx context.Context, res abci.ResponseCommit, changeSet []*StoreKVPair) error
}
```

Expand Down Expand Up @@ -267,16 +267,16 @@ We will modify the `FinalizeBlock` and `Commit` methods to pass ABCI requests an
to any streaming service hooks registered with the `BaseApp`.

```go
func (app *BaseApp) FinalizeBlock(req abci.FinalizeBlockRequest) abci.FinalizeBlockResponse {
func (app *BaseApp) FinalizeBlock(req abci.RequestFinalizeBlock) abci.ResponseFinalizeBlock {

var abciRes abci.FinalizeBlockResponse
var abciRes abci.ResponseFinalizeBlock
defer func() {
// call the streaming service hook with the FinalizeBlock messages
for _, abciListener := range app.abciListeners {
ctx := app.finalizeState.ctx
blockHeight := ctx.BlockHeight()
if app.abciListenersAsync {
go func(req abci.FinalizeBlockRequest, res abci.FinalizeBlockResponse) {
go func(req abci.RequestFinalizeBlock, res abci.ResponseFinalizeBlock) {
if err := app.abciListener.FinalizeBlock(blockHeight, req, res); err != nil {
app.logger.Error("FinalizeBlock listening hook failed", "height", blockHeight, "err", err)
}
Expand All @@ -299,11 +299,11 @@ func (app *BaseApp) FinalizeBlock(req abci.FinalizeBlockRequest) abci.FinalizeBl
```

```go
func (app *BaseApp) Commit() abci.CommitResponse {
func (app *BaseApp) Commit() abci.ResponseCommit {

...

res := abci.CommitResponse{
res := abci.ResponseCommit{
Data: commitID.Hash,
RetainHeight: retainHeight,
}
Expand All @@ -314,7 +314,7 @@ func (app *BaseApp) Commit() abci.CommitResponse {
blockHeight := ctx.BlockHeight()
changeSet := app.cms.PopStateCache()
if app.abciListenersAsync {
go func(res abci.CommitResponse, changeSet []store.StoreKVPair) {
go func(res abci.ResponseCommit, changeSet []store.StoreKVPair) {
if err := app.abciListener.ListenCommit(ctx, res, changeSet); err != nil {
app.logger.Error("ListenCommit listening hook failed", "height", blockHeight, "err", err)
}
Expand Down Expand Up @@ -433,13 +433,13 @@ type GRPCClient struct {
client ABCIListenerServiceClient
}

func (m *GRPCClient) ListenFinalizeBlock(goCtx context.Context, req abci.FinalizeBlockRequest, res abci.FinalizeBlockResponse) error {
func (m *GRPCClient) ListenFinalizeBlock(goCtx context.Context, req abci.RequestFinalizeBlock, res abci.ResponseFinalizeBlock) error {
ctx := sdk.UnwrapSDKContext(goCtx)
_, err := m.client.ListenDeliverTx(ctx, &ListenDeliverTxRequest{BlockHeight: ctx.BlockHeight(), Req: req, Res: res})
return err
}

func (m *GRPCClient) ListenCommit(goCtx context.Context, res abci.CommitResponse, changeSet []store.StoreKVPair) error {
func (m *GRPCClient) ListenCommit(goCtx context.Context, res abci.ResponseCommit, changeSet []store.StoreKVPair) error {
ctx := sdk.UnwrapSDKContext(goCtx)
_, err := m.client.ListenCommit(ctx, &ListenCommitRequest{BlockHeight: ctx.BlockHeight(), Res: res, ChangeSet: changeSet})
return err
Expand Down Expand Up @@ -471,11 +471,11 @@ And the pre-compiled Go plugin `Impl`(*this is only used for plugins that are wr
// ABCIListener is the implementation of the baseapp.ABCIListener interface
type ABCIListener struct{}

func (m *ABCIListenerPlugin) ListenFinalizeBlock(ctx context.Context, req abci.FinalizeBlockRequest, res abci.FinalizeBlockResponse) error {
func (m *ABCIListenerPlugin) ListenFinalizeBlock(ctx context.Context, req abci.RequestFinalizeBlock, res abci.ResponseFinalizeBlock) error {
// send data to external system
}

func (m *ABCIListenerPlugin) ListenCommit(ctx context.Context, res abci.CommitResponse, changeSet []store.StoreKVPair) error {
func (m *ABCIListenerPlugin) ListenCommit(ctx context.Context, res abci.ResponseCommit, changeSet []store.StoreKVPair) error {
// send data to external system
}

Expand Down Expand Up @@ -529,7 +529,7 @@ func NewStreamingPlugin(name string, logLevel string) (interface{}, error) {

We propose a `RegisterStreamingPlugin` function for the App to register `NewStreamingPlugin`s with the App's BaseApp.
Streaming plugins can be of `Any` type; therefore, the function takes in an interface vs a concrete type.
For example, we could have plugins of `ABCIListener`, `WasmListener` or `IBCListener`. Note that `RegisterStreamingPlugin` function
For example, we could have plugins of `ABCIListener`, `WasmListener` or `IBCListener`. Note that `RegisterStreamingPluing` function
is helper function and not a requirement. Plugin registration can easily be moved from the App to the BaseApp directly.

```go
Expand Down Expand Up @@ -720,5 +720,5 @@ These changes will provide a means of subscribing to KVStore state changes in re

### Neutral

* Introduces additionalbut optionalcomplexity to configuring and running a cosmos application
* Introduces additional- but optional- complexity to configuring and running a cosmos application
* If an application developer opts to use these features to expose data, they need to be aware of the ramifications/risks of that data exposure as it pertains to the specifics of their application
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,16 @@ A new database snapshot will be created in every `EndBlocker` and identified by
NOTE: `Commit` must be called exactly once per block. Otherwise we risk going out of sync for the version number and block height.
NOTE: For the Cosmos SDK storage, we may consider splitting that interface into `Committer` and `PruningCommitter` - only the multiroot should implement `PruningCommitter` (cache and prefix store don't need pruning).

Number of historical versions for `abci.QueryRequest` and state sync snapshots is part of a node configuration, not a chain configuration (configuration implied by the blockchain consensus). A configuration should allow to specify number of past blocks and number of past blocks modulo some number (eg: 100 past blocks and one snapshot every 100 blocks for past 2000 blocks). Archival nodes can keep all past versions.
Number of historical versions for `abci.RequestQuery` and state sync snapshots is part of a node configuration, not a chain configuration (configuration implied by the blockchain consensus). A configuration should allow to specify number of past blocks and number of past blocks modulo some number (eg: 100 past blocks and one snapshot every 100 blocks for past 2000 blocks). Archival nodes can keep all past versions.

Pruning old snapshots is effectively done by a database. Whenever we update a record in `SC`, SMT won't update nodes - instead it creates new nodes on the update path, without removing the old one. Since we are snapshotting each block, we need to change that mechanism to immediately remove orphaned nodes from the database. This is a safe operation - snapshots will keep track of the records and make it available when accessing past versions.

To manage the active snapshots we will either use a DB _max number of snapshots_ option (if available), or we will remove DB snapshots in the `EndBlocker`. The latter option can be done efficiently by identifying snapshots with block height and calling a store function to remove past versions.

#### Accessing old state versions

One of the functional requirements is to access old state. This is done through `abci.QueryRequest` structure. The version is specified by a block height (so we query for an object by a key `K` at block height `H`). The number of old versions supported for `abci.QueryRequest` is configurable. Accessing an old state is done by using available snapshots.
`abci.QueryRequest` doesn't need old state of `SC` unless the `prove=true` parameter is set. The SMT merkle proof must be included in the `abci.QueryResponse` only if both `SC` and `SS` have a snapshot for requested version.
One of the functional requirements is to access old state. This is done through `abci.RequestQuery` structure. The version is specified by a block height (so we query for an object by a key `K` at block height `H`). The number of old versions supported for `abci.RequestQuery` is configurable. Accessing an old state is done by using available snapshots.
`abci.RequestQuery` doesn't need old state of `SC` unless the `prove=true` parameter is set. The SMT merkle proof must be included in the `abci.ResponseQuery` only if both `SC` and `SS` have a snapshot for requested version.

Moreover, Cosmos SDK could provide a way to directly access a historical state. However, a state machine shouldn't do that - since the number of snapshots is configurable, it would lead to nondeterministic execution.

Expand Down
2 changes: 1 addition & 1 deletion docs/build/architecture/adr-059-test-scopes.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ exercises [HandleEquivocationEvidence](https://github.com/cosmos/cosmos-sdk/blob
keeper.

Example 3 - Integration suite app configurations may also be specified via golang (not
YAML as above) [statically](https://github.com/cosmos/cosmos-sdk/blob/main/x/nft/testutil/app_config.go) or [dynamically](https://github.com/cosmos/cosmos-sdk/blob/8c23f6f957d1c0bedd314806d1ac65bea59b084c/tests/integration/bank/keeper/keeper_test.go#L129-L134).
YAML as above) [statically](https://github.com/cosmos/cosmos-sdk/blob/main/contrib/x/nft/testutil/app_config.go) or [dynamically](https://github.com/cosmos/cosmos-sdk/blob/8c23f6f957d1c0bedd314806d1ac65bea59b084c/tests/integration/bank/keeper/keeper_test.go#L129-L134).

#### Limitations

Expand Down
2 changes: 1 addition & 1 deletion docs/build/architecture/adr-060-abci-1.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ Instead, we will define an additional ABCI interface method on the existing
or `EndBlock`. This new interface method will be defined as follows:

```go
ProcessProposal(sdk.Context, abci.ProcessProposalRequest) error {}
ProcessProposal(sdk.Context, abci.RequestProcessProposal) error {}
```

Note, we must call `ProcessProposal` with a new internal branched state on the
Expand Down
2 changes: 0 additions & 2 deletions docs/build/architecture/adr-063-core-module-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,6 @@ func NewKeeper(logger log.Logger) Keeper {
}
```

```

### Core `AppModule` extension interfaces


Expand Down
22 changes: 11 additions & 11 deletions docs/build/architecture/adr-064-abci-2.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ vote extensions.
We propose the following new handlers for applications to implement:

```go
type ExtendVoteHandler func(sdk.Context, abci.ExtendVoteRequest) abci.ExtendVoteResponse
type VerifyVoteExtensionHandler func(sdk.Context, abci.VerifyVoteExtensionRequest) abci.VerifyVoteExtensionResponse
type ExtendVoteHandler func(sdk.Context, abci.RequestExtendVote) abci.ResponseExtendVote
type VerifyVoteExtensionHandler func(sdk.Context, abci.RequestVerifyVoteExtension) abci.ResponseVerifyVoteExtension
```

An ephemeral context and state will be supplied to both handlers. The
Expand Down Expand Up @@ -144,7 +144,7 @@ type VoteExtensionHandler struct {

// ExtendVoteHandler can do something with h.mk and possibly h.state to create
// a vote extension, such as fetching a series of prices for supported assets.
func (h VoteExtensionHandler) ExtendVoteHandler(ctx sdk.Context, req abci.ExtendVoteRequest) abci.ExtendVoteResponse {
func (h VoteExtensionHandler) ExtendVoteHandler(ctx sdk.Context, req abci.RequestExtendVote) abci.ResponseExtendVote {
prices := GetPrices(ctx, h.mk.Assets())
bz, err := EncodePrices(h.cdc, prices)
if err != nil {
Expand All @@ -156,30 +156,30 @@ func (h VoteExtensionHandler) ExtendVoteHandler(ctx sdk.Context, req abci.Extend
// NOTE: Vote extensions can be overridden since we can timeout in a round.
SetPrices(h.state, req, bz)

return abci.ExtendVoteResponse{VoteExtension: bz}
return abci.ResponseExtendVote{VoteExtension: bz}
}

// VerifyVoteExtensionHandler can do something with h.state and req to verify
// the req.VoteExtension field, such as ensuring the provided oracle prices are
// within some valid range of our prices.
func (h VoteExtensionHandler) VerifyVoteExtensionHandler(ctx sdk.Context, req abci.VerifyVoteExtensionRequest) abci.VerifyVoteExtensionResponse {
func (h VoteExtensionHandler) VerifyVoteExtensionHandler(ctx sdk.Context, req abci.RequestVerifyVoteExtension) abci.ResponseVerifyVoteExtension {
prices, err := DecodePrices(h.cdc, req.VoteExtension)
if err != nil {
log("failed to decode vote extension", "err", err)
return abci.VerifyVoteExtensionResponse{Status: REJECT}
return abci.ResponseVerifyVoteExtension{Status: REJECT}
}

if err := ValidatePrices(h.state, req, prices); err != nil {
log("failed to validate vote extension", "prices", prices, "err", err)
return abci.VerifyVoteExtensionResponse{Status: REJECT}
return abci.ResponseVerifyVoteExtension{Status: REJECT}
}

// store updated vote extensions at the given height
//
// NOTE: Vote extensions can be overridden since we can timeout in a round.
SetPrices(h.state, req, req.VoteExtension)

return abci.VerifyVoteExtensionResponse{Status: ACCEPT}
return abci.ResponseVerifyVoteExtension{Status: ACCEPT}
}
```

Expand Down Expand Up @@ -301,7 +301,7 @@ during `ProcessProposal` because during replay, CometBFT will NOT call `ProcessP
which would result in an incomplete state view.

```go
func (a MyApp) PreBlocker(ctx sdk.Context, req *abci.FinalizeBlockRequest) error {
func (a MyApp) PreBlocker(ctx sdk.Context, req *abci.RequestFinalizeBlock) error {
voteExts := GetVoteExtensions(ctx, req.Txs)

// Process and perform some compute on vote extensions, storing any resulting
Expand Down Expand Up @@ -350,7 +350,7 @@ legacy ABCI types, e.g. `LegacyBeginBlockRequest` and `LegacyEndBlockRequest`. O
we can come up with new types and names altogether.

```go
func (app *BaseApp) FinalizeBlock(req abci.FinalizeBlockRequest) (*abci.FinalizeBlockResponse, error) {
func (app *BaseApp) FinalizeBlock(req abci.RequestFinalizeBlock) (*abci.ResponseFinalizeBlock, error) {
ctx := ...

if app.preBlocker != nil {
Expand All @@ -375,7 +375,7 @@ func (app *BaseApp) FinalizeBlock(req abci.FinalizeBlockRequest) (*abci.Finalize
endBlockResp, err := app.endBlock(app.finalizeBlockState.ctx)
appendBlockEventAttr(beginBlockResp.Events, "end_block")

return abci.FinalizeBlockResponse{
return abci.ResponseFinalizeBlock{
TxResults: txExecResults,
Events: joinEvents(beginBlockResp.Events, endBlockResp.Events),
ValidatorUpdates: endBlockResp.ValidatorUpdates,
Expand Down
Loading