Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: auto-set block timestamp for historical queries #15448

Merged
merged 22 commits into from
Mar 28, 2023
Merged
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
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