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

refactor!: abstractions for snapshot and pruning; snapshot intervals eventually pruned; unit tests #11496

Merged
Merged
Show file tree
Hide file tree
Changes from 64 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
8261885
refactor: abstractions for snapshot and pruning; snapshot intervals a…
p0mvn Mar 29, 2022
271314a
fix GetBlockRetentionHeight
p0mvn Mar 30, 2022
640c7a6
avoid snapshots/store implementing Store interface
p0mvn Mar 30, 2022
bc55f11
always use testutil.GetTempDir for creating a temp dir in tests
p0mvn Mar 30, 2022
5613d2a
use os.MkdirTemp for creating temp dir
p0mvn Mar 30, 2022
a0d29c6
changelog
p0mvn Mar 30, 2022
d7449dd
rename pruningTypes to pruningtypes
p0mvn Apr 1, 2022
aef77b5
rename snapshotTypes to snapshotypes
p0mvn Apr 1, 2022
a7c0311
update pruning default with correct values, update pruning everything…
p0mvn Apr 1, 2022
d66ed29
fix pruning options unit test to reflect the updated default value
p0mvn Apr 1, 2022
d12d255
address functional and security related comments
p0mvn Apr 8, 2022
8e420a7
storetypes
p0mvn Apr 8, 2022
4e66ff3
snapshottypes
p0mvn Apr 8, 2022
c314381
restore import order in abci_test.go
p0mvn Apr 8, 2022
fff18ad
import order in basepp_test.go
p0mvn Apr 8, 2022
99c303a
import order in baseapp/options.go
p0mvn Apr 8, 2022
64b9f35
import order
p0mvn Apr 8, 2022
55bac3b
make format on changed files
p0mvn Apr 8, 2022
a54fd34
add unit test for NewPruningOptionsFromString
p0mvn Apr 8, 2022
1751e81
add TestLoadPruningHeights_PruneNothing
p0mvn Apr 8, 2022
ecde568
address previousHeight == 0 guard and nits
p0mvn Apr 8, 2022
17bcbbd
fix snapshot height must be positive check
p0mvn Apr 9, 2022
f6462e1
godoc for init
p0mvn Apr 11, 2022
20e8651
return 0 if negative previousVersion is given to the pruning manager.…
p0mvn Apr 11, 2022
d915e89
remove GetCommitKVStores
p0mvn Apr 11, 2022
2ec8fad
remove type aliases from store types
p0mvn Apr 11, 2022
950ab26
revert pruning options pointer
p0mvn Apr 11, 2022
1c7b5a9
revert snapshot options pointer
p0mvn Apr 11, 2022
fdf3515
refactor: syncronize pruning manager (#187)
p0mvn Apr 13, 2022
d9eb77c
fix rebase problem in tests
p0mvn Apr 13, 2022
cd5ed77
increase code coverage by covering panics in pruning manager unit tests
p0mvn Apr 13, 2022
1a62435
increase coverage in pruning options
p0mvn Apr 13, 2022
9400186
NegativeHeightsError implementation and format
p0mvn Apr 13, 2022
94739dc
Update pruning/README.md
p0mvn Apr 13, 2022
631a756
update order of declarations in pruning manager
p0mvn Apr 13, 2022
ffa4d6d
Merge branch 'roman/upstream/snapshot-pruning-refactor' of github.com…
p0mvn Apr 13, 2022
5a504af
new goroutine is handled by SnapshotIfApplicable caller
p0mvn Apr 13, 2022
2893b32
synchronous SnapshotIfApplicable
p0mvn Apr 14, 2022
25b4bd1
return a copy of pruneHeights in GetFlushAndResetPruningHeights
p0mvn Apr 14, 2022
7f610e1
godoc for pruning manager
p0mvn Apr 14, 2022
9c92dc4
Update error message in baseapp/baseapp.go
p0mvn Apr 14, 2022
8ef356b
sdk import in util_test.go
p0mvn Apr 14, 2022
c482cd3
Apply suggestions from code review in pruning/README.md
p0mvn Apr 14, 2022
091061c
Apply more style suggestions from code review
p0mvn Apr 14, 2022
f2ea6b0
remove junk test files
p0mvn Apr 14, 2022
611560f
style fix in simapp/simd/cmd/root.go
p0mvn Apr 14, 2022
678ed17
remove unused import in baseapp
p0mvn Apr 14, 2022
a6c861a
Merge branch 'master' into roman/upstream/snapshot-pruning-refactor
p0mvn Apr 16, 2022
dab1ba8
resolve merge conflict
p0mvn Apr 16, 2022
d40790c
update snapshots/README.md
p0mvn Apr 16, 2022
54068ce
Update SnapshotIntervalOff comment in snapshots/types/options.go
p0mvn Apr 16, 2022
70c2043
Update pruneSnapshotHeightsKey pruning/manager.go
p0mvn Apr 16, 2022
f3b5485
update SetSnapshotInterval comment
p0mvn Apr 16, 2022
2023fa3
remove snapshot store type
p0mvn Apr 16, 2022
823971f
remove pruning and snapshot wrappers from store types
p0mvn Apr 16, 2022
73b75ee
fix HandleHeight comment in pruning manager
p0mvn Apr 16, 2022
986f6ff
Merge branch 'master' into roman/upstream/snapshot-pruning-refactor
p0mvn Apr 19, 2022
19669c4
Merge branch 'master' into roman/upstream/snapshot-pruning-refactor
p0mvn Apr 19, 2022
bbe9d5e
snapshot happens in a separate goroutine
p0mvn Apr 20, 2022
073b664
Merge branch 'master' into roman/upstream/snapshot-pruning-refactor
p0mvn Apr 21, 2022
2dc26e5
set snapshot interval on multistore in baseapp instead of snapshot ma…
p0mvn Apr 21, 2022
d6a3569
Merge branch 'master' into roman/upstream/snapshot-pruning-refactor
p0mvn Apr 21, 2022
8eee2f7
fix snapshot manager unit tests
p0mvn Apr 21, 2022
5d85f99
Merge branch 'master' into roman/upstream/snapshot-pruning-refactor
p0mvn Apr 21, 2022
eb5a3b3
Merge branch 'master' into roman/upstream/snapshot-pruning-refactor
alexanderbez Apr 21, 2022
e53691a
Update CHANGELOG.md
p0mvn Apr 21, 2022
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 @@ -85,6 +85,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### API Breaking Changes

* [\#11496](https://github.com/cosmos/cosmos-sdk/pull/11496) refactor abstractions for snapshot and pruning; snapshot intervals eventually pruned; unit tests.
p0mvn marked this conversation as resolved.
Show resolved Hide resolved
* (types) [\#11689](https://github.com/cosmos/cosmos-sdk/pull/11689) Make `Coins#Sub` and `Coins#SafeSub` consistent with `Coins#Add`.
* (store)[\#11152](https://github.com/cosmos/cosmos-sdk/pull/11152) Remove `keep-every` from pruning options.
* [\#10950](https://github.com/cosmos/cosmos-sdk/pull/10950) Add `envPrefix` parameter to `cmd.Execute`.
Expand Down
42 changes: 6 additions & 36 deletions baseapp/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,9 +338,7 @@ func (app *BaseApp) Commit() (res abci.ResponseCommit) {
app.halt()
}

if app.snapshotInterval > 0 && uint64(header.Height)%app.snapshotInterval == 0 {
go app.snapshot(header.Height)
}
go app.snapshotManager.SnapshotIfApplicable(header.Height)

return abci.ResponseCommit{
Data: commitID.Hash,
Expand Down Expand Up @@ -370,36 +368,6 @@ func (app *BaseApp) halt() {
os.Exit(0)
}

// snapshot takes a snapshot of the current state and prunes any old snapshottypes.
func (app *BaseApp) snapshot(height int64) {
if app.snapshotManager == nil {
app.logger.Info("snapshot manager not configured")
return
}

app.logger.Info("creating state snapshot", "height", height)

snapshot, err := app.snapshotManager.Create(uint64(height))
if err != nil {
app.logger.Error("failed to create state snapshot", "height", height, "err", err)
return
}

app.logger.Info("completed state snapshot", "height", height, "format", snapshot.Format)

if app.snapshotKeepRecent > 0 {
app.logger.Debug("pruning state snapshots")

pruned, err := app.snapshotManager.Prune(app.snapshotKeepRecent)
if err != nil {
app.logger.Error("Failed to prune state snapshots", "err", err)
return
}

app.logger.Debug("pruned state snapshots", "pruned", pruned)
}
}

// Query implements the ABCI interface. It delegates to CommitMultiStore if it
// implements Queryable.
func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
Expand Down Expand Up @@ -718,9 +686,11 @@ func (app *BaseApp) GetBlockRetentionHeight(commitHeight int64) int64 {
retentionHeight = commitHeight - cp.Evidence.MaxAgeNumBlocks
}

if app.snapshotInterval > 0 && app.snapshotKeepRecent > 0 {
v := commitHeight - int64((app.snapshotInterval * uint64(app.snapshotKeepRecent)))
retentionHeight = minNonZero(retentionHeight, v)
if app.snapshotManager != nil {
snapshotRetentionHeights := app.snapshotManager.GetSnapshotBlockRetentionHeights()
if snapshotRetentionHeights > 0 {
retentionHeight = minNonZero(retentionHeight, commitHeight-snapshotRetentionHeights)
}
}

v := commitHeight - int64(app.minRetainBlocks)
Expand Down
28 changes: 19 additions & 9 deletions baseapp/abci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,24 @@ import (

"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmprototypes "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"

"github.com/cosmos/cosmos-sdk/baseapp"
pruningtypes "github.com/cosmos/cosmos-sdk/pruning/types"
snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types"
"github.com/cosmos/cosmos-sdk/snapshots"
"github.com/cosmos/cosmos-sdk/testutil"
)

func TestGetBlockRentionHeight(t *testing.T) {
logger := defaultLogger()
db := dbm.NewMemDB()
name := t.Name()

snapshotStore, err := snapshots.NewStore(dbm.NewMemDB(), testutil.GetTempDir(t))
require.NoError(t, err)

testCases := map[string]struct {
bapp *baseapp.BaseApp
maxAgeBlocks int64
Expand All @@ -38,17 +44,18 @@ func TestGetBlockRentionHeight(t *testing.T) {
"pruning iavl snapshot only": {
bapp: baseapp.NewBaseApp(
name, logger, db,
baseapp.SetPruning(pruningtypes.NewPruningOptions(pruningtypes.PruningNothing)),
baseapp.SetMinRetainBlocks(1),
baseapp.SetSnapshot(snapshotStore, snapshottypes.NewSnapshotOptions(10000, 1)),
),
maxAgeBlocks: 0,
commitHeight: 499000,
expected: 498999,
expected: 489000,
},
"pruning state sync snapshot only": {
bapp: baseapp.NewBaseApp(
name, logger, db,
baseapp.SetSnapshotInterval(50000),
baseapp.SetSnapshotKeepRecent(3),
baseapp.SetSnapshot(snapshotStore, snapshottypes.NewSnapshotOptions(50000, 3)),
baseapp.SetMinRetainBlocks(1),
),
maxAgeBlocks: 0,
Expand All @@ -67,8 +74,9 @@ func TestGetBlockRentionHeight(t *testing.T) {
"pruning all conditions": {
bapp: baseapp.NewBaseApp(
name, logger, db,
baseapp.SetPruning(pruningtypes.NewCustomPruningOptions(0, 0)),
baseapp.SetMinRetainBlocks(400000),
baseapp.SetSnapshotInterval(50000), baseapp.SetSnapshotKeepRecent(3),
baseapp.SetSnapshot(snapshotStore, snapshottypes.NewSnapshotOptions(50000, 3)),
),
maxAgeBlocks: 362880,
commitHeight: 499000,
Expand All @@ -77,8 +85,9 @@ func TestGetBlockRentionHeight(t *testing.T) {
"no pruning due to no persisted state": {
bapp: baseapp.NewBaseApp(
name, logger, db,
baseapp.SetPruning(pruningtypes.NewCustomPruningOptions(0, 0)),
baseapp.SetMinRetainBlocks(400000),
baseapp.SetSnapshotInterval(50000), baseapp.SetSnapshotKeepRecent(3),
baseapp.SetSnapshot(snapshotStore, snapshottypes.NewSnapshotOptions(50000, 3)),
),
maxAgeBlocks: 362880,
commitHeight: 10000,
Expand All @@ -87,8 +96,9 @@ func TestGetBlockRentionHeight(t *testing.T) {
"disable pruning": {
bapp: baseapp.NewBaseApp(
name, logger, db,
baseapp.SetPruning(pruningtypes.NewCustomPruningOptions(0, 0)),
baseapp.SetMinRetainBlocks(0),
baseapp.SetSnapshotInterval(50000), baseapp.SetSnapshotKeepRecent(3),
baseapp.SetSnapshot(snapshotStore, snapshottypes.NewSnapshotOptions(50000, 3)),
),
maxAgeBlocks: 362880,
commitHeight: 499000,
Expand Down Expand Up @@ -126,10 +136,10 @@ func TestBaseAppCreateQueryContext(t *testing.T) {
name := t.Name()
app := baseapp.NewBaseApp(name, logger, db)

app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: 1}})
app.BeginBlock(abci.RequestBeginBlock{Header: tmprototypes.Header{Height: 1}})
app.Commit()

app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: 2}})
app.BeginBlock(abci.RequestBeginBlock{Header: tmprototypes.Header{Height: 2}})
app.Commit()

testCases := []struct {
Expand Down
26 changes: 12 additions & 14 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package baseapp

import (
"context"
"errors"
"fmt"

abci "github.com/tendermint/tendermint/abci/types"
Expand Down Expand Up @@ -62,9 +61,7 @@ type BaseApp struct { // nolint: maligned
fauxMerkleMode bool // if true, IAVL MountStores uses MountStoresDB for simulation speed.

// manages snapshots, i.e. dumps of app state at certain intervals
snapshotManager *snapshots.Manager
snapshotInterval uint64 // block interval between state sync snapshots
snapshotKeepRecent uint32 // recent state sync snapshots to keep
snapshotManager *snapshots.Manager

// volatile states:
//
Expand Down Expand Up @@ -252,7 +249,7 @@ func (app *BaseApp) LoadLatestVersion() error {
return fmt.Errorf("failed to load latest version: %w", err)
}

return app.init()
return app.Init()
}

// DefaultStoreLoader will be used by default and loads the latest version
Expand Down Expand Up @@ -284,7 +281,7 @@ func (app *BaseApp) LoadVersion(version int64) error {
return fmt.Errorf("failed to load version %d: %w", version, err)
}

return app.init()
return app.Init()
}

// LastCommitID returns the last CommitID of the multistore.
Expand All @@ -297,7 +294,11 @@ func (app *BaseApp) LastBlockHeight() int64 {
return app.cms.LastCommitID().Version
}

func (app *BaseApp) init() error {
// Init initializes the app. It seals the app, preventing any
// further modifications. In addition, it validates the app against
// the earlier provided settings. Returns an error if validation fails.
// nil otherwise. Panics if the app is already sealed.
func (app *BaseApp) Init() error {
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
if app.sealed {
panic("cannot call initFromMainStore: baseapp already sealed")
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
}
Expand All @@ -306,14 +307,11 @@ func (app *BaseApp) init() error {
app.setCheckState(tmproto.Header{})
app.Seal()

// make sure the snapshot interval is a multiple of the pruning KeepEvery interval
if app.snapshotManager != nil && app.snapshotInterval > 0 {
if _, ok := app.cms.(*rootmulti.Store); !ok {
return errors.New("state sync snapshots require a rootmulti store")
}
rms, ok := app.cms.(*rootmulti.Store)
if !ok {
return fmt.Errorf("invalid commit multi-store; expected %T, got: %T", &rootmulti.Store{}, app.cms)
}

return nil
return rms.GetPruning().Validate()
}

func (app *BaseApp) setMinGasPrices(gasPrices sdk.DecCoins) {
Expand Down
Loading