From 5237639138d9c0997e6b9f00a6ec34cd571bdecf Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 5 Sep 2018 21:48:32 -0700 Subject: [PATCH 1/7] fix prefixIterator --- store/prefixstore.go | 124 ++++++++++++++++++++++++++++++++------ store/prefixstore_test.go | 71 +++++++++++++++++++++- 2 files changed, 174 insertions(+), 21 deletions(-) diff --git a/store/prefixstore.go b/store/prefixstore.go index 835a210385..af9e59b643 100644 --- a/store/prefixstore.go +++ b/store/prefixstore.go @@ -1,6 +1,7 @@ package store import ( + "bytes" "io" sdk "github.com/cosmos/cosmos-sdk/types" @@ -13,6 +14,18 @@ type prefixStore struct { prefix []byte } +func clone(bz []byte) (res []byte) { + res = make([]byte, len(bz)) + copy(res, bz) + return +} + +func (s prefixStore) key(key []byte) (res []byte) { + res = clone(s.prefix) + res = append(res, key...) + return +} + // Implements Store func (s prefixStore) GetStoreType() StoreType { return s.parent.GetStoreType() @@ -30,22 +43,23 @@ func (s prefixStore) CacheWrapWithTrace(w io.Writer, tc TraceContext) CacheWrap // Implements KVStore func (s prefixStore) Get(key []byte) []byte { - return s.parent.Get(append(s.prefix, key...)) + res := s.parent.Get(s.key(key)) + return res } // Implements KVStore func (s prefixStore) Has(key []byte) bool { - return s.parent.Has(append(s.prefix, key...)) + return s.parent.Has(s.key(key)) } // Implements KVStore func (s prefixStore) Set(key, value []byte) { - s.parent.Set(append(s.prefix, key...), value) + s.parent.Set(s.key(key), value) } // Implements KVStore func (s prefixStore) Delete(key []byte) { - s.parent.Delete(append(s.prefix, key...)) + s.parent.Delete(s.key(key)) } // Implements KVStore @@ -59,53 +73,83 @@ func (s prefixStore) Gas(meter GasMeter, config GasConfig) KVStore { } // Implements KVStore +// Check https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db.go#L106 func (s prefixStore) Iterator(start, end []byte) Iterator { + newstart := append(clone(s.prefix), start...) + + var newend []byte if end == nil { - end = sdk.PrefixEndBytes(s.prefix) + newend = cpIncr(s.prefix) } else { - end = append(s.prefix, end...) + newend = append(clone(s.prefix), end...) } + return prefixIterator{ prefix: s.prefix, - iter: s.parent.Iterator(append(s.prefix, start...), end), + start: newstart, + end: newend, + iter: s.parent.Iterator(newstart, newend), } + } // Implements KVStore +// Check https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db.go#L129 func (s prefixStore) ReverseIterator(start, end []byte) Iterator { - if end == nil { - end = sdk.PrefixEndBytes(s.prefix) + var newstart []byte + if start == nil { + newstart = cpIncr(s.prefix) } else { - end = append(s.prefix, end...) + newstart = append(clone(s.prefix), start...) } + + var newend []byte + if end == nil { + newend = cpIncr(s.prefix) + } else { + newend = append(clone(s.prefix), end...) + } + + iter := s.parent.ReverseIterator(newstart, newend) + if start == nil { + skipOne(iter, cpIncr(s.prefix)) + } + return prefixIterator{ prefix: s.prefix, - iter: s.parent.ReverseIterator(start, end), + start: newstart, + end: newend, + iter: iter, } } type prefixIterator struct { - prefix []byte - - iter Iterator + prefix []byte + start, end []byte + iter Iterator + valid bool } // Implements Iterator -func (iter prefixIterator) Domain() (start []byte, end []byte) { - start, end = iter.iter.Domain() - start = start[len(iter.prefix):] - end = end[len(iter.prefix):] - return +func (iter prefixIterator) Domain() ([]byte, []byte) { + return iter.start, iter.end } // Implements Iterator func (iter prefixIterator) Valid() bool { - return iter.iter.Valid() + return iter.valid && iter.iter.Valid() } // Implements Iterator func (iter prefixIterator) Next() { + if !iter.valid { + panic("prefixIterator invalid, cannot call Next()") + } iter.iter.Next() + if !iter.iter.Valid() || !bytes.HasPrefix(iter.iter.Key(), iter.prefix) { + iter.iter.Close() + iter.valid = false + } } // Implements Iterator @@ -124,3 +168,43 @@ func (iter prefixIterator) Value() []byte { func (iter prefixIterator) Close() { iter.iter.Close() } + +// copied from github.com/tendermint/tendermint/libs/db/prefix_db.go +func stripPrefix(key []byte, prefix []byte) []byte { + if len(key) < len(prefix) || !bytes.Equal(key[:len(prefix)], prefix) { + panic("should not happen") + } + return key[len(prefix):] +} + +// wrapping sdk.PrefixEndBytes +func cpIncr(bz []byte) []byte { + return sdk.PrefixEndBytes(bz) +} + +// copied from github.com/tendermint/tendermint/libs/db/util.go +func cpDecr(bz []byte) (ret []byte) { + if len(bz) == 0 { + panic("cpDecr expects non-zero bz length") + } + ret = clone(bz) + for i := len(bz) - 1; i >= 0; i-- { + if ret[i] > byte(0x00) { + ret[i]-- + return + } + ret[i] = byte(0xFF) + if i == 0 { + return nil + } + } + return nil +} + +func skipOne(iter Iterator, skipKey []byte) { + if iter.Valid() { + if bytes.Equal(iter.Key(), skipKey) { + iter.Next() + } + } +} diff --git a/store/prefixstore_test.go b/store/prefixstore_test.go index 49bc68037a..cf50b9dd4c 100644 --- a/store/prefixstore_test.go +++ b/store/prefixstore_test.go @@ -1,6 +1,7 @@ package store import ( + "bytes" "math/rand" "testing" @@ -105,7 +106,75 @@ func TestPrefixStoreIterate(t *testing.T) { pIter.Next() } - require.Equal(t, bIter.Valid(), pIter.Valid()) bIter.Close() pIter.Close() } + +func TestPrefixStoreIteratorEdgeCase(t *testing.T) { + db := dbm.NewMemDB() + baseStore := dbStoreAdapter{db} + + // overflow in cpIncr + prefix := []byte{0xAA, 0xFF, 0xFF} + prefixStore := baseStore.Prefix(prefix) + + // ascending order + baseStore.Set([]byte{0xAA, 0xFF, 0xFE}, []byte{}) + baseStore.Set([]byte{0xAA, 0xFF, 0xFE, 0x00}, []byte{}) + baseStore.Set([]byte{0xAA, 0xFF, 0xFF}, []byte{}) + baseStore.Set([]byte{0xAA, 0xFF, 0xFF, 0x00}, []byte{}) + baseStore.Set([]byte{0xAB}, []byte{}) + baseStore.Set([]byte{0xAB, 0x00}, []byte{}) + baseStore.Set([]byte{0xAB, 0x00, 0x00}, []byte{}) + + for iter := prefixStore.Iterator(nil, nil); iter.Valid(); iter.Next() { + require.True(t, bytes.HasPrefix(iter.Key(), prefix)) + } +} + +func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) { + db := dbm.NewMemDB() + baseStore := dbStoreAdapter{db} + + // overflow in cpIncr + prefix := []byte{0xAA, 0xFF, 0xFF} + prefixStore := baseStore.Prefix(prefix) + + // descending order + baseStore.Set([]byte{0xAB, 0x00, 0x00}, []byte{}) + baseStore.Set([]byte{0xAB, 0x00}, []byte{}) + baseStore.Set([]byte{0xAB}, []byte{}) + baseStore.Set([]byte{0xAA, 0xFF, 0xFF, 0x00}, []byte{}) + baseStore.Set([]byte{0xAA, 0xFF, 0xFF}, []byte{}) + baseStore.Set([]byte{0xAA, 0xFF, 0xFE, 0x00}, []byte{}) + baseStore.Set([]byte{0xAA, 0xFF, 0xFE}, []byte{}) + + iter := prefixStore.ReverseIterator(nil, nil) + for ; iter.Valid(); iter.Next() { + require.True(t, bytes.HasPrefix(iter.Key(), prefix)) + } + + iter.Close() + + db = dbm.NewMemDB() + baseStore = dbStoreAdapter{db} + + // underflow in cpDecr + prefix = []byte{0xAA, 0x00, 0x00} + prefixStore = baseStore.Prefix(prefix) + + baseStore.Set([]byte{0xAB, 0x00, 0x01, 0x00, 0x00}, []byte{}) + baseStore.Set([]byte{0xAB, 0x00, 0x01, 0x00}, []byte{}) + baseStore.Set([]byte{0xAB, 0x00, 0x01}, []byte{}) + baseStore.Set([]byte{0xAA, 0x00, 0x00, 0x00}, []byte{}) + baseStore.Set([]byte{0xAA, 0x00, 0x00}, []byte{}) + baseStore.Set([]byte{0xA9, 0xFF, 0xFF, 0x00}, []byte{}) + baseStore.Set([]byte{0xA9, 0xFF, 0xFF}, []byte{}) + + iter = prefixStore.ReverseIterator(nil, nil) + for ; iter.Valid(); iter.Next() { + require.True(t, bytes.HasPrefix(iter.Key(), prefix)) + } + + iter.Close() +} From 5091d1688dfa7ae391735fd2edb1bb1914a5da3d Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 11 Sep 2018 15:59:58 +0900 Subject: [PATCH 2/7] partially apply requests --- store/prefixstore.go | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/store/prefixstore.go b/store/prefixstore.go index af9e59b643..c060bf5c36 100644 --- a/store/prefixstore.go +++ b/store/prefixstore.go @@ -14,15 +14,15 @@ type prefixStore struct { prefix []byte } -func clone(bz []byte) (res []byte) { - res = make([]byte, len(bz)) +func cloneAppend(bz []byte, tail []byte) (res []byte) { + res = make([]byte, len(bz)+len(tail)) copy(res, bz) + res = append(res, bz...) return } func (s prefixStore) key(key []byte) (res []byte) { - res = clone(s.prefix) - res = append(res, key...) + res = cloneAppend(s.prefix, key) return } @@ -75,19 +75,19 @@ func (s prefixStore) Gas(meter GasMeter, config GasConfig) KVStore { // Implements KVStore // Check https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db.go#L106 func (s prefixStore) Iterator(start, end []byte) Iterator { - newstart := append(clone(s.prefix), start...) + newstart := cloneAppend(s.prefix, start) var newend []byte if end == nil { newend = cpIncr(s.prefix) } else { - newend = append(clone(s.prefix), end...) + newend = cloneAppend(s.prefix, end) } return prefixIterator{ prefix: s.prefix, - start: newstart, - end: newend, + start: start, + end: end, iter: s.parent.Iterator(newstart, newend), } @@ -100,14 +100,14 @@ func (s prefixStore) ReverseIterator(start, end []byte) Iterator { if start == nil { newstart = cpIncr(s.prefix) } else { - newstart = append(clone(s.prefix), start...) + newstart = cloneAppend(s.prefix, start) } var newend []byte if end == nil { - newend = cpIncr(s.prefix) + newend = cpDecr(s.prefix) } else { - newend = append(clone(s.prefix), end...) + newend = cloneAppend(s.prefix, end) } iter := s.parent.ReverseIterator(newstart, newend) @@ -117,8 +117,8 @@ func (s prefixStore) ReverseIterator(start, end []byte) Iterator { return prefixIterator{ prefix: s.prefix, - start: newstart, - end: newend, + start: start, + end: end, iter: iter, } } @@ -187,7 +187,8 @@ func cpDecr(bz []byte) (ret []byte) { if len(bz) == 0 { panic("cpDecr expects non-zero bz length") } - ret = clone(bz) + ret = make([]byte, len(bz)) + copy(ret, bz) for i := len(bz) - 1; i >= 0; i-- { if ret[i] > byte(0x00) { ret[i]-- From c770e74571dc5ef9c12b062e391028de47bc82c7 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 9 Oct 2018 03:06:16 +0900 Subject: [PATCH 3/7] fix cloneAppend --- store/prefixstore.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/prefixstore.go b/store/prefixstore.go index c060bf5c36..2b70a28ff8 100644 --- a/store/prefixstore.go +++ b/store/prefixstore.go @@ -17,7 +17,7 @@ type prefixStore struct { func cloneAppend(bz []byte, tail []byte) (res []byte) { res = make([]byte, len(bz)+len(tail)) copy(res, bz) - res = append(res, bz...) + copy(res[len(bz):], tail) return } From e7c76eb344ad211ccb63f969dcb2e67e89dcf859 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 9 Oct 2018 04:43:55 +0900 Subject: [PATCH 4/7] port tests from tmlibs, fix tests --- store/prefixstore.go | 31 ++--- store/prefixstore_test.go | 230 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 238 insertions(+), 23 deletions(-) diff --git a/store/prefixstore.go b/store/prefixstore.go index 2b70a28ff8..a29459e4e8 100644 --- a/store/prefixstore.go +++ b/store/prefixstore.go @@ -9,6 +9,10 @@ import ( var _ KVStore = prefixStore{} +// prefixStore is similar with tendermint/tendermint/libs/db/prefix_db +// both gives access only to the limited subset of the store +// for convinience or safety + type prefixStore struct { parent KVStore prefix []byte @@ -84,13 +88,9 @@ func (s prefixStore) Iterator(start, end []byte) Iterator { newend = cloneAppend(s.prefix, end) } - return prefixIterator{ - prefix: s.prefix, - start: start, - end: end, - iter: s.parent.Iterator(newstart, newend), - } + iter := s.parent.Iterator(newstart, newend) + return newPrefixIterator(s.prefix, start, end, iter) } // Implements KVStore @@ -115,12 +115,7 @@ func (s prefixStore) ReverseIterator(start, end []byte) Iterator { skipOne(iter, cpIncr(s.prefix)) } - return prefixIterator{ - prefix: s.prefix, - start: start, - end: end, - iter: iter, - } + return newPrefixIterator(s.prefix, start, end, iter) } type prefixIterator struct { @@ -130,6 +125,16 @@ type prefixIterator struct { valid bool } +func newPrefixIterator(prefix, start, end []byte, parent Iterator) prefixIterator { + return prefixIterator{ + prefix: prefix, + start: start, + end: end, + iter: parent, + valid: parent.Valid() && bytes.HasPrefix(parent.Key(), prefix), + } +} + // Implements Iterator func (iter prefixIterator) Domain() ([]byte, []byte) { return iter.start, iter.end @@ -155,7 +160,7 @@ func (iter prefixIterator) Next() { // Implements Iterator func (iter prefixIterator) Key() (key []byte) { key = iter.iter.Key() - key = key[len(iter.prefix):] + key = stripPrefix(key, iter.prefix) return } diff --git a/store/prefixstore_test.go b/store/prefixstore_test.go index cf50b9dd4c..499f30d500 100644 --- a/store/prefixstore_test.go +++ b/store/prefixstore_test.go @@ -1,7 +1,6 @@ package store import ( - "bytes" "math/rand" "testing" @@ -127,9 +126,17 @@ func TestPrefixStoreIteratorEdgeCase(t *testing.T) { baseStore.Set([]byte{0xAB, 0x00}, []byte{}) baseStore.Set([]byte{0xAB, 0x00, 0x00}, []byte{}) - for iter := prefixStore.Iterator(nil, nil); iter.Valid(); iter.Next() { - require.True(t, bytes.HasPrefix(iter.Key(), prefix)) - } + iter := prefixStore.Iterator(nil, nil) + + checkDomain(t, iter, nil, nil) + checkItem(t, iter, []byte{}, bz("")) + checkNext(t, iter, true) + checkItem(t, iter, []byte{0x00}, bz("")) + checkNext(t, iter, false) + + checkInvalid(t, iter) + + iter.Close() } func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) { @@ -150,9 +157,14 @@ func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) { baseStore.Set([]byte{0xAA, 0xFF, 0xFE}, []byte{}) iter := prefixStore.ReverseIterator(nil, nil) - for ; iter.Valid(); iter.Next() { - require.True(t, bytes.HasPrefix(iter.Key(), prefix)) - } + + checkDomain(t, iter, nil, nil) + checkItem(t, iter, []byte{0x00}, bz("")) + checkNext(t, iter, true) + checkItem(t, iter, []byte{}, bz("")) + checkNext(t, iter, false) + + checkInvalid(t, iter) iter.Close() @@ -172,9 +184,207 @@ func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) { baseStore.Set([]byte{0xA9, 0xFF, 0xFF}, []byte{}) iter = prefixStore.ReverseIterator(nil, nil) - for ; iter.Valid(); iter.Next() { - require.True(t, bytes.HasPrefix(iter.Key(), prefix)) - } + + checkDomain(t, iter, nil, nil) + checkItem(t, iter, []byte{0x00}, bz("")) + checkNext(t, iter, true) + checkItem(t, iter, []byte{}, bz("")) + checkNext(t, iter, false) + + checkInvalid(t, iter) iter.Close() } + +// Tests below are ported from https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db_test.go + +func mockStoreWithStuff() sdk.KVStore { + db := dbm.NewMemDB() + store := dbStoreAdapter{db} + // Under "key" prefix + store.Set(bz("key"), bz("value")) + store.Set(bz("key1"), bz("value1")) + store.Set(bz("key2"), bz("value2")) + store.Set(bz("key3"), bz("value3")) + store.Set(bz("something"), bz("else")) + store.Set(bz(""), bz("")) + store.Set(bz("k"), bz("val")) + store.Set(bz("ke"), bz("valu")) + store.Set(bz("kee"), bz("valuu")) + return store +} + +func checkValue(t *testing.T, store sdk.KVStore, key []byte, expected []byte) { + bz := store.Get(key) + require.Equal(t, expected, bz) +} + +func checkValid(t *testing.T, itr sdk.Iterator, expected bool) { + valid := itr.Valid() + require.Equal(t, expected, valid) +} + +func checkNext(t *testing.T, itr sdk.Iterator, expected bool) { + itr.Next() + valid := itr.Valid() + require.Equal(t, expected, valid) +} + +func checkDomain(t *testing.T, itr sdk.Iterator, start, end []byte) { + ds, de := itr.Domain() + require.Equal(t, start, ds) + require.Equal(t, end, de) +} + +func checkItem(t *testing.T, itr sdk.Iterator, key, value []byte) { + require.Exactly(t, key, itr.Key()) + require.Exactly(t, value, itr.Value()) +} + +func checkInvalid(t *testing.T, itr sdk.Iterator) { + checkValid(t, itr, false) + checkKeyPanics(t, itr) + checkValuePanics(t, itr) + checkNextPanics(t, itr) +} + +func checkKeyPanics(t *testing.T, itr sdk.Iterator) { + require.Panics(t, func() { itr.Key() }) +} + +func checkValuePanics(t *testing.T, itr sdk.Iterator) { + require.Panics(t, func() { itr.Value() }) +} + +func checkNextPanics(t *testing.T, itr sdk.Iterator) { + require.Panics(t, func() { itr.Next() }) +} + +func TestPrefixDBSimple(t *testing.T) { + store := mockStoreWithStuff() + pstore := store.Prefix(bz("key")) + + checkValue(t, pstore, bz("key"), nil) + checkValue(t, pstore, bz(""), bz("value")) + checkValue(t, pstore, bz("key1"), nil) + checkValue(t, pstore, bz("1"), bz("value1")) + checkValue(t, pstore, bz("key2"), nil) + checkValue(t, pstore, bz("2"), bz("value2")) + checkValue(t, pstore, bz("key3"), nil) + checkValue(t, pstore, bz("3"), bz("value3")) + checkValue(t, pstore, bz("something"), nil) + checkValue(t, pstore, bz("k"), nil) + checkValue(t, pstore, bz("ke"), nil) + checkValue(t, pstore, bz("kee"), nil) +} + +func TestPrefixDBIterator1(t *testing.T) { + store := mockStoreWithStuff() + pstore := store.Prefix(bz("key")) + + itr := pstore.Iterator(nil, nil) + checkDomain(t, itr, nil, nil) + checkItem(t, itr, bz(""), bz("value")) + checkNext(t, itr, true) + checkItem(t, itr, bz("1"), bz("value1")) + checkNext(t, itr, true) + checkItem(t, itr, bz("2"), bz("value2")) + checkNext(t, itr, true) + checkItem(t, itr, bz("3"), bz("value3")) + checkNext(t, itr, false) + checkInvalid(t, itr) + itr.Close() +} + +func TestPrefixDBIterator2(t *testing.T) { + store := mockStoreWithStuff() + pstore := store.Prefix(bz("key")) + + itr := pstore.Iterator(nil, bz("")) + checkDomain(t, itr, nil, bz("")) + checkInvalid(t, itr) + itr.Close() +} + +func TestPrefixDBIterator3(t *testing.T) { + store := mockStoreWithStuff() + pstore := store.Prefix(bz("key")) + + itr := pstore.Iterator(bz(""), nil) + checkDomain(t, itr, bz(""), nil) + checkItem(t, itr, bz(""), bz("value")) + checkNext(t, itr, true) + checkItem(t, itr, bz("1"), bz("value1")) + checkNext(t, itr, true) + checkItem(t, itr, bz("2"), bz("value2")) + checkNext(t, itr, true) + checkItem(t, itr, bz("3"), bz("value3")) + checkNext(t, itr, false) + checkInvalid(t, itr) + itr.Close() +} + +func TestPrefixDBIterator4(t *testing.T) { + store := mockStoreWithStuff() + pstore := store.Prefix(bz("key")) + + itr := pstore.Iterator(bz(""), bz("")) + checkDomain(t, itr, bz(""), bz("")) + checkInvalid(t, itr) + itr.Close() +} + +func TestPrefixDBReverseIterator1(t *testing.T) { + store := mockStoreWithStuff() + pstore := store.Prefix(bz("key")) + + itr := pstore.ReverseIterator(nil, nil) + checkDomain(t, itr, nil, nil) + checkItem(t, itr, bz("3"), bz("value3")) + checkNext(t, itr, true) + checkItem(t, itr, bz("2"), bz("value2")) + checkNext(t, itr, true) + checkItem(t, itr, bz("1"), bz("value1")) + checkNext(t, itr, true) + checkItem(t, itr, bz(""), bz("value")) + checkNext(t, itr, false) + checkInvalid(t, itr) + itr.Close() +} + +func TestPrefixDBReverseIterator2(t *testing.T) { + store := mockStoreWithStuff() + pstore := store.Prefix(bz("key")) + + itr := pstore.ReverseIterator(nil, bz("")) + checkDomain(t, itr, nil, bz("")) + checkItem(t, itr, bz("3"), bz("value3")) + checkNext(t, itr, true) + checkItem(t, itr, bz("2"), bz("value2")) + checkNext(t, itr, true) + checkItem(t, itr, bz("1"), bz("value1")) + checkNext(t, itr, false) + checkInvalid(t, itr) + itr.Close() +} + +func TestPrefixDBReverseIterator3(t *testing.T) { + store := mockStoreWithStuff() + pstore := store.Prefix(bz("key")) + + itr := pstore.ReverseIterator(bz(""), nil) + checkDomain(t, itr, bz(""), nil) + checkItem(t, itr, bz(""), bz("value")) + checkNext(t, itr, false) + checkInvalid(t, itr) + itr.Close() +} + +func TestPrefixDBReverseIterator4(t *testing.T) { + store := mockStoreWithStuff() + pstore := store.Prefix(bz("key")) + + itr := pstore.ReverseIterator(bz(""), bz("")) + checkInvalid(t, itr) + itr.Close() +} From 43b3352c87d8e44c8d968cd06b14c58efbaf59b3 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 9 Oct 2018 05:06:40 +0900 Subject: [PATCH 5/7] fix Close() --- store/prefixstore.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/store/prefixstore.go b/store/prefixstore.go index a29459e4e8..04d268057d 100644 --- a/store/prefixstore.go +++ b/store/prefixstore.go @@ -152,13 +152,15 @@ func (iter prefixIterator) Next() { } iter.iter.Next() if !iter.iter.Valid() || !bytes.HasPrefix(iter.iter.Key(), iter.prefix) { - iter.iter.Close() iter.valid = false } } // Implements Iterator func (iter prefixIterator) Key() (key []byte) { + if !iter.valid { + panic("prefixIterator invalid, cannot call Key()") + } key = iter.iter.Key() key = stripPrefix(key, iter.prefix) return @@ -166,6 +168,9 @@ func (iter prefixIterator) Key() (key []byte) { // Implements Iterator func (iter prefixIterator) Value() []byte { + if !iter.valid() { + panic("prefixIterator invalid, cannot call Value()") + } return iter.iter.Value() } From ed9b29c856801db32c6759170fbf32c30d248c38 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 9 Oct 2018 05:18:43 +0900 Subject: [PATCH 6/7] fix typo --- store/prefixstore.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/prefixstore.go b/store/prefixstore.go index 04d268057d..981d821311 100644 --- a/store/prefixstore.go +++ b/store/prefixstore.go @@ -168,7 +168,7 @@ func (iter prefixIterator) Key() (key []byte) { // Implements Iterator func (iter prefixIterator) Value() []byte { - if !iter.valid() { + if !iter.valid { panic("prefixIterator invalid, cannot call Value()") } return iter.iter.Value() From 0cbb37ff034396e837dc1cd81b82032cd068159e Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 9 Oct 2018 05:37:18 +0900 Subject: [PATCH 7/7] rm Close() from Next() --- store/prefixstore.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/store/prefixstore.go b/store/prefixstore.go index 981d821311..55af1084e3 100644 --- a/store/prefixstore.go +++ b/store/prefixstore.go @@ -118,6 +118,8 @@ func (s prefixStore) ReverseIterator(start, end []byte) Iterator { return newPrefixIterator(s.prefix, start, end, iter) } +var _ sdk.Iterator = (*prefixIterator)(nil) + type prefixIterator struct { prefix []byte start, end []byte @@ -125,8 +127,8 @@ type prefixIterator struct { valid bool } -func newPrefixIterator(prefix, start, end []byte, parent Iterator) prefixIterator { - return prefixIterator{ +func newPrefixIterator(prefix, start, end []byte, parent Iterator) *prefixIterator { + return &prefixIterator{ prefix: prefix, start: start, end: end, @@ -136,17 +138,17 @@ func newPrefixIterator(prefix, start, end []byte, parent Iterator) prefixIterato } // Implements Iterator -func (iter prefixIterator) Domain() ([]byte, []byte) { +func (iter *prefixIterator) Domain() ([]byte, []byte) { return iter.start, iter.end } // Implements Iterator -func (iter prefixIterator) Valid() bool { +func (iter *prefixIterator) Valid() bool { return iter.valid && iter.iter.Valid() } // Implements Iterator -func (iter prefixIterator) Next() { +func (iter *prefixIterator) Next() { if !iter.valid { panic("prefixIterator invalid, cannot call Next()") } @@ -157,7 +159,7 @@ func (iter prefixIterator) Next() { } // Implements Iterator -func (iter prefixIterator) Key() (key []byte) { +func (iter *prefixIterator) Key() (key []byte) { if !iter.valid { panic("prefixIterator invalid, cannot call Key()") } @@ -167,7 +169,7 @@ func (iter prefixIterator) Key() (key []byte) { } // Implements Iterator -func (iter prefixIterator) Value() []byte { +func (iter *prefixIterator) Value() []byte { if !iter.valid { panic("prefixIterator invalid, cannot call Value()") } @@ -175,7 +177,7 @@ func (iter prefixIterator) Value() []byte { } // Implements Iterator -func (iter prefixIterator) Close() { +func (iter *prefixIterator) Close() { iter.iter.Close() }