Skip to content

Commit

Permalink
feat: auto-set block timestamp for historical queries (#15448)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderbez authored Mar 28, 2023
1 parent f15cbac commit ee9774a
Show file tree
Hide file tree
Showing 15 changed files with 292 additions and 110 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Improvements

* [#15448](https://github.com/cosmos/cosmos-sdk/pull/15448) Automatically populate the block timestamp for historical queries. In contexts where the block timestamp is needed for previous states, the timestamp will now be set. Note, when querying against a node it must be re-synced in order to be able to automatically populate the block timestamp. Otherwise, the block timestamp will be populated for heights going forward once upgraded.
* (x/gov) [#15554](https://github.com/cosmos/cosmos-sdk/pull/15554) Add proposal result log in `active_proposal` event. When a proposal passes but fails to execute, the proposal result is logged in the `active_proposal` event.
* (mempool) [#15328](https://github.com/cosmos/cosmos-sdk/pull/15328) Improve the `PriorityNonceMempool`
* Support generic transaction prioritization, instead of `ctx.Priority()`
Expand Down
180 changes: 138 additions & 42 deletions api/cosmos/store/v1beta1/commit_info.pulsar.go

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions baseapp/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
grpcstatus "google.golang.org/grpc/status"

errorsmod "cosmossdk.io/errors"
"cosmossdk.io/store/rootmulti"
snapshottypes "cosmossdk.io/store/snapshots/types"
storetypes "cosmossdk.io/store/types"

Expand Down Expand Up @@ -456,6 +457,11 @@ func (app *BaseApp) Commit() abci.ResponseCommit {
header := app.deliverState.ctx.BlockHeader()
retainHeight := app.GetBlockRetentionHeight(header.Height)

rms, ok := app.cms.(*rootmulti.Store)
if ok {
rms.SetCommitHeader(header)
}

// Write the DeliverTx state into branched storage and commit the MultiStore.
// The write to the DeliverTx state writes all state transitions to the root
// MultiStore (app.cms) so when Commit() is called is persists those values.
Expand Down Expand Up @@ -810,6 +816,16 @@ func (app *BaseApp) CreateQueryContext(height int64, prove bool) (sdk.Context, e
WithMinGasPrices(app.minGasPrices).
WithBlockHeight(height)

if height != lastBlockHeight {
rms, ok := app.cms.(*rootmulti.Store)
if ok {
cInfo, err := rms.GetCommitInfo(height)
if cInfo != nil && err == nil {
ctx = ctx.WithBlockTime(cInfo.Timestamp)
}
}
}

return ctx, nil
}

Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ require (

// Below are the long-lived replace of the Cosmos SDK
replace (
cosmossdk.io/store => ./store
cosmossdk.io/x/tx => ./x/tx
// use cosmos fork of keyring
github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0
// dgrijalva/jwt-go is deprecated and doesn't receive security updates.
Expand Down
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,6 @@ cosmossdk.io/log v0.1.0 h1:Vnexi+KzUCjmqq/m93teAxjt5biWFfZ5PI1imx2IJw8=
cosmossdk.io/log v0.1.0/go.mod h1:p95Wq6mDY3SREMc4y7+QU9Uwy3nyvfpWGD1iSaFkVFs=
cosmossdk.io/math v1.0.0 h1:ro9w7eKx23om2tZz/VM2Pf+z2WAbGX1yDQQOJ6iGeJw=
cosmossdk.io/math v1.0.0/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k=
cosmossdk.io/store v0.1.0-alpha.1 h1:NGomhLUXzAxvK4OF8+yP6eNUG5i4LwzOzx+S494pTCg=
cosmossdk.io/store v0.1.0-alpha.1/go.mod h1:kmCMbhrleCZ6rDZPY/EGNldNvPebFNyVPFYp+pv05/k=
cosmossdk.io/x/tx v0.3.1-0.20230321155358-6522dd1731b5 h1:AlvyRc7f7Py1mv254vrqjIIuykCnitHIz2T+nup3bU0=
cosmossdk.io/x/tx v0.3.1-0.20230321155358-6522dd1731b5/go.mod h1:FNkSEMbLP9NFdTfrbslNUtNS7OXf3wgZeJyXzfRPa4c=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
Expand Down
7 changes: 5 additions & 2 deletions proto/cosmos/store/v1beta1/commit_info.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ syntax = "proto3";
package cosmos.store.v1beta1;

import "gogoproto/gogo.proto";
import "google/protobuf/timestamp.proto";

option go_package = "cosmossdk.io/store/types";

// CommitInfo defines commit information used by the multi-store when committing
// a version/height.
message CommitInfo {
int64 version = 1;
repeated StoreInfo store_infos = 2 [(gogoproto.nullable) = false];
int64 version = 1;
repeated StoreInfo store_infos = 2 [(gogoproto.nullable) = false];
google.protobuf.Timestamp timestamp = 3
[(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
}

// StoreInfo defines store-specific commit information. It contains a reference
Expand Down
1 change: 1 addition & 0 deletions simapp/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ require (
replace (
// TODO tag all extracted modules after SDK refactor
cosmossdk.io/api => ../api
cosmossdk.io/store => ../store
cosmossdk.io/tools/confix => ../tools/confix
cosmossdk.io/tools/rosetta => ../tools/rosetta
cosmossdk.io/x/evidence => ../x/evidence
Expand Down
2 changes: 0 additions & 2 deletions simapp/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,6 @@ cosmossdk.io/log v0.1.0 h1:Vnexi+KzUCjmqq/m93teAxjt5biWFfZ5PI1imx2IJw8=
cosmossdk.io/log v0.1.0/go.mod h1:p95Wq6mDY3SREMc4y7+QU9Uwy3nyvfpWGD1iSaFkVFs=
cosmossdk.io/math v1.0.0 h1:ro9w7eKx23om2tZz/VM2Pf+z2WAbGX1yDQQOJ6iGeJw=
cosmossdk.io/math v1.0.0/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k=
cosmossdk.io/store v0.1.0-alpha.1 h1:NGomhLUXzAxvK4OF8+yP6eNUG5i4LwzOzx+S494pTCg=
cosmossdk.io/store v0.1.0-alpha.1/go.mod h1:kmCMbhrleCZ6rDZPY/EGNldNvPebFNyVPFYp+pv05/k=
cosmossdk.io/x/tx v0.3.1-0.20230321155358-6522dd1731b5 h1:AlvyRc7f7Py1mv254vrqjIIuykCnitHIz2T+nup3bU0=
cosmossdk.io/x/tx v0.3.1-0.20230321155358-6522dd1731b5/go.mod h1:FNkSEMbLP9NFdTfrbslNUtNS7OXf3wgZeJyXzfRPa4c=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
Expand Down
2 changes: 1 addition & 1 deletion store/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ require (
golang.org/x/exp v0.0.0-20230321023759-10a507213a29
google.golang.org/genproto v0.0.0-20230320184635-7606e756e683 // indirect
google.golang.org/grpc v1.54.0
google.golang.org/protobuf v1.30.0 // indirect
google.golang.org/protobuf v1.30.0
gotest.tools/v3 v3.4.0
)

Expand Down
73 changes: 42 additions & 31 deletions store/rootmulti/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"cosmossdk.io/log"
abci "github.com/cometbft/cometbft/abci/types"
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
dbm "github.com/cosmos/cosmos-db"
protoio "github.com/cosmos/gogoproto/io"
gogotypes "github.com/cosmos/gogoproto/types"
Expand Down Expand Up @@ -67,16 +68,13 @@ type Store struct {
lazyLoading bool
initialVersion int64
removalMap map[types.StoreKey]bool

traceWriter io.Writer
traceContext types.TraceContext
traceContextMutex sync.Mutex

interBlockCache types.MultiStorePersistentCache

listeners map[types.StoreKey]*types.MemoryListener

metrics metrics.StoreMetrics
traceWriter io.Writer
traceContext types.TraceContext
traceContextMutex sync.Mutex
interBlockCache types.MultiStorePersistentCache
listeners map[types.StoreKey]*types.MemoryListener
metrics metrics.StoreMetrics
commitHeader cmtproto.Header
}

var (
Expand Down Expand Up @@ -217,7 +215,7 @@ func (rs *Store) loadVersion(ver int64, upgrades *types.StoreUpgrades) error {
// load old data if we are not version 0
if ver != 0 {
var err error
cInfo, err = getCommitInfo(rs.db, ver)
cInfo, err = rs.GetCommitInfo(ver)
if err != nil {
return err
}
Expand Down Expand Up @@ -469,7 +467,12 @@ func (rs *Store) Commit() types.CommitID {
version = previousHeight + 1
}

if rs.commitHeader.Height != version {
rs.logger.Debug("commit header and version mismatch", "header_height", rs.commitHeader.Height, "version", version)
}

rs.lastCommitInfo = commitStores(version, rs.stores, rs.removalMap)
rs.lastCommitInfo.Timestamp = rs.commitHeader.Time
defer rs.flushMetadata(rs.db, version, rs.lastCommitInfo)

// remove remnants of removed stores
Expand All @@ -480,6 +483,7 @@ func (rs *Store) Commit() types.CommitID {
delete(rs.keysByName, sk.Name())
}
}

// reset the removalMap
rs.removalMap = make(map[types.StoreKey]bool)

Expand Down Expand Up @@ -705,7 +709,7 @@ func (rs *Store) Query(req abci.RequestQuery) abci.ResponseQuery {
if res.Height == rs.lastCommitInfo.Version {
commitInfo = rs.lastCommitInfo
} else {
commitInfo, err = getCommitInfo(rs.db, res.Height)
commitInfo, err = rs.GetCommitInfo(res.Height)
if err != nil {
return types.QueryResult(err, false)
}
Expand Down Expand Up @@ -1048,6 +1052,32 @@ func (rs *Store) RollbackToVersion(target int64) error {
return rs.LoadLatestVersion()
}

// SetCommitHeader sets the commit block header of the store.
func (rs *Store) SetCommitHeader(h cmtproto.Header) {
rs.commitHeader = h
}

// GetCommitInfo attempts to retrieve CommitInfo for a given version/height. It
// will return an error if no CommitInfo exists, we fail to unmarshal the record
// or if we cannot retrieve the object from the DB.
func (rs *Store) GetCommitInfo(ver int64) (*types.CommitInfo, error) {
cInfoKey := fmt.Sprintf(commitInfoKeyFmt, ver)

bz, err := rs.db.Get([]byte(cInfoKey))
if err != nil {
return nil, errorsmod.Wrap(err, "failed to get commit info")
} else if bz == nil {
return nil, errors.New("no commit info found")
}

cInfo := &types.CommitInfo{}
if err = cInfo.Unmarshal(bz); err != nil {
return nil, errorsmod.Wrap(err, "failed unmarshal commit info")
}

return cInfo, nil
}

func (rs *Store) flushMetadata(db dbm.DB, version int64, cInfo *types.CommitInfo) {
rs.logger.Debug("flushing metadata", "height", version)
batch := db.NewBatch()
Expand Down Expand Up @@ -1143,25 +1173,6 @@ func commitStores(version int64, storeMap map[types.StoreKey]types.CommitKVStore
}
}

// Gets commitInfo from disk.
func getCommitInfo(db dbm.DB, ver int64) (*types.CommitInfo, error) {
cInfoKey := fmt.Sprintf(commitInfoKeyFmt, ver)

bz, err := db.Get([]byte(cInfoKey))
if err != nil {
return nil, errorsmod.Wrap(err, "failed to get commit info")
} else if bz == nil {
return nil, errors.New("no commit info found")
}

cInfo := &types.CommitInfo{}
if err = cInfo.Unmarshal(bz); err != nil {
return nil, errorsmod.Wrap(err, "failed unmarshal commit info")
}

return cInfo, nil
}

func flushCommitInfo(batch dbm.Batch, version int64, cInfo *types.CommitInfo) {
bz, err := cInfo.Marshal()
if err != nil {
Expand Down
12 changes: 6 additions & 6 deletions store/rootmulti/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ func TestMultistoreLoadWithUpgrade(t *testing.T) {
expectedCommitID := getExpectedCommitID(store, 1)
checkStore(t, store, expectedCommitID, commitID)

ci, err := getCommitInfo(db, 1)
ci, err := store.GetCommitInfo(1)
require.NoError(t, err)
require.Equal(t, int64(1), ci.Version)
require.Equal(t, 3, len(ci.StoreInfos))
Expand Down Expand Up @@ -294,7 +294,7 @@ func TestMultistoreLoadWithUpgrade(t *testing.T) {
require.Equal(t, v4, rl4.Get(k4))

// check commitInfo in storage
ci, err = getCommitInfo(db, 2)
ci, err = reload.GetCommitInfo(2)
require.NoError(t, err)
require.Equal(t, int64(2), ci.Version)
require.Equal(t, 3, len(ci.StoreInfos), ci.StoreInfos)
Expand Down Expand Up @@ -349,7 +349,7 @@ func TestMultiStoreRestart(t *testing.T) {

multi.Commit()

cinfo, err := getCommitInfo(multi.db, int64(i))
cinfo, err := multi.GetCommitInfo(int64(i))
require.NoError(t, err)
require.Equal(t, int64(i), cinfo.Version)
}
Expand All @@ -364,7 +364,7 @@ func TestMultiStoreRestart(t *testing.T) {

multi.Commit()

flushedCinfo, err := getCommitInfo(multi.db, 3)
flushedCinfo, err := multi.GetCommitInfo(3)
require.Nil(t, err)
require.NotEqual(t, initCid, flushedCinfo, "CID is different after flush to disk")

Expand All @@ -374,7 +374,7 @@ func TestMultiStoreRestart(t *testing.T) {

multi.Commit()

postFlushCinfo, err := getCommitInfo(multi.db, 4)
postFlushCinfo, err := multi.GetCommitInfo(4)
require.NoError(t, err)
require.Equal(t, int64(4), postFlushCinfo.Version, "Commit changed after in-memory commit")

Expand Down Expand Up @@ -757,7 +757,7 @@ func TestCommitOrdered(t *testing.T) {
typeID := multi.Commit()
require.Equal(t, int64(1), typeID.Version)

ci, err := getCommitInfo(db, 1)
ci, err := multi.GetCommitInfo(1)
require.NoError(t, err)
require.Equal(t, int64(1), ci.Version)
require.Equal(t, 3, len(ci.StoreInfos))
Expand Down
Loading

0 comments on commit ee9774a

Please sign in to comment.