Skip to content

Commit

Permalink
Merge PR #5630: v0.38.1 RC1
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderbez authored Feb 11, 2020
1 parent f3b82c5 commit 766ce82
Show file tree
Hide file tree
Showing 17 changed files with 561 additions and 147 deletions.
21 changes: 20 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,24 @@ Ref: https://keepachangelog.com/en/1.0.0/

## [Unreleased]

## [v0.38.1] - TBD

### Improvements

* (modules) [\#5597](https://github.com/cosmos/cosmos-sdk/pull/5597) Add `amount` event attribute to the `complete_unbonding`
and `complete_redelegation` events that reflect the total balances of the completed unbondings and redelegations
respectively.

### Bug Fixes

* (types) [\#5579](https://github.com/cosmos/cosmos-sdk/pull/5579) The IAVL `Store#Commit` method has been refactored to
delete a flushed version if it is not a snapshot version. The root multi-store now keeps track of `commitInfo` instead
of `types.CommitID`. During `Commit` of the root multi-store, `lastCommitInfo` is updated from the saved state
and is only flushed to disk if it is a snapshot version. During `Query` of the root multi-store, if the request height
is the latest height, we'll use the store's `lastCommitInfo`. Otherwise, we fetch `commitInfo` from disk.
* (x/bank) [\#5531](https://github.com/cosmos/cosmos-sdk/issues/5531) Added missing amount event to MsgMultiSend, emitted for each output.
* (x/gov) [\#5622](https://github.com/cosmos/cosmos-sdk/pull/5622) Track any events emitted from a proposal's handler upon successful execution.

## [v0.38.0] - 2020-01-23

### State Machine Breaking
Expand Down Expand Up @@ -2862,7 +2880,8 @@ BUG FIXES:
<!-- Release links -->
[Unreleased]: https://github.com/cosmos/cosmos-sdk/compare/v0.38.0...HEAD
[Unreleased]: https://github.com/cosmos/cosmos-sdk/compare/v0.38.1...HEAD
[v0.38.1]: https://github.com/cosmos/cosmos-sdk/releases/tag/v0.38.1
[v0.38.0]: https://github.com/cosmos/cosmos-sdk/releases/tag/v0.38.0
[v0.37.6]: https://github.com/cosmos/cosmos-sdk/releases/tag/v0.37.6
[v0.37.5]: https://github.com/cosmos/cosmos-sdk/releases/tag/v0.37.5
Expand Down
86 changes: 84 additions & 2 deletions baseapp/baseapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func TestMountStores(t *testing.T) {
// Test that LoadLatestVersion actually does.
func TestLoadVersion(t *testing.T) {
logger := defaultLogger()
pruningOpt := SetPruning(store.PruneSyncable)
pruningOpt := SetPruning(store.PruneNothing)
db := dbm.NewMemDB()
name := t.Name()
app := NewBaseApp(name, logger, db, nil, pruningOpt)
Expand Down Expand Up @@ -293,7 +293,7 @@ func TestAppVersionSetterGetter(t *testing.T) {

func TestLoadVersionInvalid(t *testing.T) {
logger := log.NewNopLogger()
pruningOpt := SetPruning(store.PruneSyncable)
pruningOpt := SetPruning(store.PruneNothing)
db := dbm.NewMemDB()
name := t.Name()
app := NewBaseApp(name, logger, db, nil, pruningOpt)
Expand Down Expand Up @@ -326,6 +326,88 @@ func TestLoadVersionInvalid(t *testing.T) {
require.Error(t, err)
}

func TestLoadVersionPruning(t *testing.T) {
logger := log.NewNopLogger()
pruningOptions := store.PruningOptions{
KeepEvery: 2,
SnapshotEvery: 6,
}
pruningOpt := SetPruning(pruningOptions)
db := dbm.NewMemDB()
name := t.Name()
app := NewBaseApp(name, logger, db, nil, pruningOpt)

// make a cap key and mount the store
capKey := sdk.NewKVStoreKey(MainStoreKey)
app.MountStores(capKey)
err := app.LoadLatestVersion(capKey) // needed to make stores non-nil
require.Nil(t, err)

emptyCommitID := sdk.CommitID{}

// fresh store has zero/empty last commit
lastHeight := app.LastBlockHeight()
lastID := app.LastCommitID()
require.Equal(t, int64(0), lastHeight)
require.Equal(t, emptyCommitID, lastID)

// execute a block
header := abci.Header{Height: 1}
app.BeginBlock(abci.RequestBeginBlock{Header: header})
res := app.Commit()

// execute a block, collect commit ID
header = abci.Header{Height: 2}
app.BeginBlock(abci.RequestBeginBlock{Header: header})
res = app.Commit()
commitID2 := sdk.CommitID{Version: 2, Hash: res.Data}

// execute a block
header = abci.Header{Height: 3}
app.BeginBlock(abci.RequestBeginBlock{Header: header})
res = app.Commit()
commitID3 := sdk.CommitID{Version: 3, Hash: res.Data}

// reload with LoadLatestVersion, check it loads last flushed version
app = NewBaseApp(name, logger, db, nil, pruningOpt)
app.MountStores(capKey)
err = app.LoadLatestVersion(capKey)
require.Nil(t, err)
testLoadVersionHelper(t, app, int64(2), commitID2)

// re-execute block 3 and check it is same CommitID
header = abci.Header{Height: 3}
app.BeginBlock(abci.RequestBeginBlock{Header: header})
res = app.Commit()
recommitID3 := sdk.CommitID{Version: 3, Hash: res.Data}
require.Equal(t, commitID3, recommitID3, "Commits of identical blocks not equal after reload")

// execute a block, collect commit ID
header = abci.Header{Height: 4}
app.BeginBlock(abci.RequestBeginBlock{Header: header})
res = app.Commit()
commitID4 := sdk.CommitID{Version: 4, Hash: res.Data}

// execute a block
header = abci.Header{Height: 5}
app.BeginBlock(abci.RequestBeginBlock{Header: header})
res = app.Commit()

// reload with LoadLatestVersion, check it loads last flushed version
app = NewBaseApp(name, logger, db, nil, pruningOpt)
app.MountStores(capKey)
err = app.LoadLatestVersion(capKey)
require.Nil(t, err)
testLoadVersionHelper(t, app, int64(4), commitID4)

// reload with LoadVersion of previous flushed version
// and check it fails since previous flush should be pruned
app = NewBaseApp(name, logger, db, nil, pruningOpt)
app.MountStores(capKey)
err = app.LoadVersion(2, capKey)
require.NotNil(t, err)
}

func testLoadVersionHelper(t *testing.T, app *BaseApp, expectedHeight int64, expectedID sdk.CommitID) {
lastHeight := app.LastBlockHeight()
lastID := app.LastCommitID()
Expand Down
2 changes: 1 addition & 1 deletion server/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ default, the application will run with Tendermint in process.
Pruning options can be provided via the '--pruning' flag. The options are as follows:
syncable: only those states not needed for state syncing will be deleted (keeps last 100 + every 10000th)
syncable: only those states not needed for state syncing will be deleted (flushes every 100th to disk and keeps every 10000th)
nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node)
everything: all saved states will be deleted, storing only the current state
Expand Down
6 changes: 3 additions & 3 deletions store/cache/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func TestGetOrSetStoreCache(t *testing.T) {
sKey := types.NewKVStoreKey("test")
tree, err := iavl.NewMutableTree(db, 100)
require.NoError(t, err)
store := iavlstore.UnsafeNewStore(tree)
store := iavlstore.UnsafeNewStore(tree, types.PruneNothing)
store2 := mngr.GetStoreCache(sKey, store)

require.NotNil(t, store2)
Expand All @@ -34,7 +34,7 @@ func TestUnwrap(t *testing.T) {
sKey := types.NewKVStoreKey("test")
tree, err := iavl.NewMutableTree(db, 100)
require.NoError(t, err)
store := iavlstore.UnsafeNewStore(tree)
store := iavlstore.UnsafeNewStore(tree, types.PruneNothing)
_ = mngr.GetStoreCache(sKey, store)

require.Equal(t, store, mngr.Unwrap(sKey))
Expand All @@ -48,7 +48,7 @@ func TestStoreCache(t *testing.T) {
sKey := types.NewKVStoreKey("test")
tree, err := iavl.NewMutableTree(db, 100)
require.NoError(t, err)
store := iavlstore.UnsafeNewStore(tree)
store := iavlstore.UnsafeNewStore(tree, types.PruneNothing)
kvStore := mngr.GetStoreCache(sKey, store)

for i := uint(0); i < cache.DefaultCommitKVStoreCacheSize*2; i++ {
Expand Down
68 changes: 58 additions & 10 deletions store/iavl/store.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package iavl

import (
"fmt"
"io"
"sync"

"github.com/pkg/errors"
"github.com/tendermint/iavl"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/merkle"
Expand All @@ -29,18 +31,38 @@ var (

// Store Implements types.KVStore and CommitKVStore.
type Store struct {
tree Tree
tree Tree
pruning types.PruningOptions
}

// LoadStore returns an IAVL Store as a CommitKVStore. Internally it will load the
// LoadStore returns an IAVL Store as a CommitKVStore. Internally, it will load the
// store's version (id) from the provided DB. An error is returned if the version
// fails to load.
func LoadStore(db dbm.DB, id types.CommitID, pruning types.PruningOptions, lazyLoading bool) (types.CommitKVStore, error) {
if !pruning.IsValid() {
return nil, fmt.Errorf("pruning options are invalid: %v", pruning)
}

var keepRecent int64

// Determine the value of keepRecent based on the following:
//
// If KeepEvery = 1, keepRecent should be 0 since there is no need to keep
// latest version in a in-memory cache.
//
// If KeepEvery > 1, keepRecent should be 1 so that state changes in between
// flushed states can be saved in the in-memory latest tree.
if pruning.KeepEvery == 1 {
keepRecent = 0
} else {
keepRecent = 1
}

tree, err := iavl.NewMutableTreeWithOpts(
db,
dbm.NewMemDB(),
defaultIAVLCacheSize,
iavl.PruningOptions(pruning.KeepEvery(), pruning.KeepRecent()),
iavl.PruningOptions(pruning.KeepEvery, keepRecent),
)
if err != nil {
return nil, err
Expand All @@ -56,15 +78,23 @@ func LoadStore(db dbm.DB, id types.CommitID, pruning types.PruningOptions, lazyL
return nil, err
}

return &Store{tree: tree}, nil
return &Store{
tree: tree,
pruning: pruning,
}, nil
}

// UnsafeNewStore returns a reference to a new IAVL Store with a given mutable
// IAVL tree reference.
// IAVL tree reference. It should only be used for testing purposes.
//
// CONTRACT: The IAVL tree should be fully loaded.
func UnsafeNewStore(tree *iavl.MutableTree) *Store {
return &Store{tree: tree}
// CONTRACT: PruningOptions passed in as argument must be the same as pruning options
// passed into iavl.MutableTree
func UnsafeNewStore(tree *iavl.MutableTree, po types.PruningOptions) *Store {
return &Store{
tree: tree,
pruning: po,
}
}

// GetImmutable returns a reference to a new store backed by an immutable IAVL
Expand All @@ -82,18 +112,36 @@ func (st *Store) GetImmutable(version int64) (*Store, error) {
return nil, err
}

return &Store{tree: &immutableTree{iTree}}, nil
return &Store{
tree: &immutableTree{iTree},
pruning: st.pruning,
}, nil
}

// Implements Committer.
// Commit commits the current store state and returns a CommitID with the new
// version and hash.
func (st *Store) Commit() types.CommitID {
// Save a new version.
hash, version, err := st.tree.SaveVersion()
if err != nil {
// TODO: Do we want to extend Commit to allow returning errors?
panic(err)
}

// If the version we saved got flushed to disk, check if previous flushed
// version should be deleted.
if st.pruning.FlushVersion(version) {
previous := version - st.pruning.KeepEvery

// Previous flushed version should only be pruned if the previous version is
// not a snapshot version OR if snapshotting is disabled (SnapshotEvery == 0).
if previous != 0 && !st.pruning.SnapshotVersion(previous) {
err := st.tree.DeleteVersion(previous)
if errCause := errors.Cause(err); errCause != nil && errCause != iavl.ErrVersionDoesNotExist {
panic(err)
}
}
}

return types.CommitID{
Version: version,
Hash: hash,
Expand Down
Loading

0 comments on commit 766ce82

Please sign in to comment.