diff --git a/app/store.go b/app/store.go index 2ad14915a..a19aa968c 100644 --- a/app/store.go +++ b/app/store.go @@ -17,6 +17,9 @@ import ( sm "github.com/cosmos/cosmos-sdk/state" ) +// DefaultHistorySize is how many blocks of history to store for ABCI queries +const DefaultHistorySize = 10 + // StoreApp contains a data store and all info needed // to perform queries and handshakes. // @@ -41,7 +44,7 @@ type StoreApp struct { // NewStoreApp creates a data store to handle queries func NewStoreApp(appName, dbName string, cacheSize int, logger log.Logger) (*StoreApp, error) { - state, err := loadState(dbName, cacheSize) + state, err := loadState(dbName, cacheSize, DefaultHistorySize) if err != nil { return nil, err } @@ -234,11 +237,11 @@ func pubKeyIndex(val *abci.Validator, list []*abci.Validator) int { return -1 } -func loadState(dbName string, cacheSize int) (*sm.State, error) { +func loadState(dbName string, cacheSize int, historySize uint64) (*sm.State, error) { // memory backed case, just for testing if dbName == "" { tree := iavl.NewVersionedTree(0, dbm.NewMemDB()) - return sm.NewState(tree), nil + return sm.NewState(tree, historySize), nil } // Expand the path fully @@ -267,5 +270,5 @@ func loadState(dbName string, cacheSize int) (*sm.State, error) { } } - return sm.NewState(tree), nil + return sm.NewState(tree, historySize), nil } diff --git a/state/merkle.go b/state/merkle.go index 2373d27d3..b30143830 100644 --- a/state/merkle.go +++ b/state/merkle.go @@ -5,17 +5,19 @@ import "github.com/tendermint/iavl" // State represents the app states, separating the commited state (for queries) // from the working state (for CheckTx and AppendTx) type State struct { - committed *Bonsai - deliverTx SimpleDB - checkTx SimpleDB + committed *Bonsai + deliverTx SimpleDB + checkTx SimpleDB + historySize uint64 } -func NewState(tree *iavl.VersionedTree) *State { +func NewState(tree *iavl.VersionedTree, historySize uint64) *State { base := NewBonsai(tree) return &State{ - committed: base, - deliverTx: base.Checkpoint(), - checkTx: base.Checkpoint(), + committed: base, + deliverTx: base.Checkpoint(), + checkTx: base.Checkpoint(), + historySize: historySize, } } @@ -51,6 +53,7 @@ func (s *State) Commit(version uint64) ([]byte, error) { return nil, err } + // store a new version var hash []byte if s.committed.Tree.Size() > 0 || s.committed.Tree.LatestVersion() > 0 { hash, err = s.committed.Tree.SaveVersion(version) @@ -59,6 +62,11 @@ func (s *State) Commit(version uint64) ([]byte, error) { } } + // release an old version + if version > s.historySize { + s.committed.Tree.DeleteVersion(version - s.historySize) + } + s.deliverTx = s.committed.Checkpoint() s.checkTx = s.committed.Checkpoint() return hash, nil diff --git a/state/merkle_test.go b/state/merkle_test.go index 9866195b4..3e4fdb724 100644 --- a/state/merkle_test.go +++ b/state/merkle_test.go @@ -66,7 +66,7 @@ func TestStateCommitHash(t *testing.T) { // make the store... tree := iavl.NewVersionedTree(0, db.NewMemDB()) - store := NewState(tree) + store := NewState(tree, 2) for n, r := range tc.rounds { // start the cache