/
iterator.go
232 lines (197 loc) · 11.2 KB
/
iterator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
package keeper
import (
"time"
db "github.com/tendermint/tm-db"
"github.com/percosis-labs/percosis/v16/x/lockup/types"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
func unlockingPrefix(isUnlocking bool) []byte {
if isUnlocking {
return types.KeyPrefixUnlocking
}
return types.KeyPrefixNotUnlocking
}
// iteratorAfterTime iterates through keys between that use prefix, and have a time.
func (k Keeper) iteratorAfterTime(ctx sdk.Context, prefix []byte, time time.Time) sdk.Iterator {
store := ctx.KVStore(k.storeKey)
timeKey := getTimeKey(time)
key := combineKeys(prefix, timeKey)
// If it’s unlockTime, then it should count as unlocked
// inclusive end bytes = key + 1, next iterator
return store.Iterator(storetypes.PrefixEndBytes(key), storetypes.PrefixEndBytes(prefix))
}
// iteratorBeforeTime iterates through keys between that use prefix, and have a time LTE max time.
func (k Keeper) iteratorBeforeTime(ctx sdk.Context, prefix []byte, maxTime time.Time) sdk.Iterator {
store := ctx.KVStore(k.storeKey)
timeKey := getTimeKey(maxTime)
key := combineKeys(prefix, timeKey)
// If it’s unlockTime, then it should count as unlocked
// inclusive end bytes = key + 1, next iterator
return store.Iterator(prefix, storetypes.PrefixEndBytes(key))
}
// iteratorDuration iterates over a domain of keys for a specified duration.
func (k Keeper) iteratorDuration(ctx sdk.Context, prefix []byte, duration time.Duration) sdk.Iterator {
durationKey := getDurationKey(duration)
key := combineKeys(prefix, durationKey)
store := ctx.KVStore(k.storeKey)
return sdk.KVStorePrefixIterator(store, key)
}
// iteratorLongerDuration iterates over a domain of keys for longer than a specified duration.
func (k Keeper) iteratorLongerDuration(ctx sdk.Context, prefix []byte, duration time.Duration) sdk.Iterator {
store := ctx.KVStore(k.storeKey)
durationKey := getDurationKey(duration)
key := combineKeys(prefix, durationKey)
// inclusive on longer side, means >= (longer or equal)
return store.Iterator(key, storetypes.PrefixEndBytes(prefix))
}
// iteratorShorterDuration iterates over a domain of keys for shorter than a specified duration.
func (k Keeper) iteratorShorterDuration(ctx sdk.Context, prefix []byte, duration time.Duration) sdk.Iterator {
store := ctx.KVStore(k.storeKey)
durationKey := getDurationKey(duration)
key := combineKeys(prefix, durationKey)
// inclusive on longer side, shorter means < (lower)
return store.Iterator(prefix, key)
}
// iterator iterates over a domain of keys.
func (k Keeper) iterator(ctx sdk.Context, prefix []byte) sdk.Iterator {
store := ctx.KVStore(k.storeKey)
return sdk.KVStorePrefixIterator(store, prefix)
}
// LockIteratorAfterTime returns the iterator to get locked coins.
func (k Keeper) LockIteratorAfterTime(ctx sdk.Context, time time.Time) sdk.Iterator {
unlockingPrefix := unlockingPrefix(true)
return k.iteratorAfterTime(ctx, combineKeys(unlockingPrefix, types.KeyPrefixLockTimestamp), time)
}
// LockIteratorBeforeTime returns the iterator to get unlockable coins.
func (k Keeper) LockIteratorBeforeTime(ctx sdk.Context, time time.Time) sdk.Iterator {
unlockingPrefix := unlockingPrefix(true)
return k.iteratorBeforeTime(ctx, combineKeys(unlockingPrefix, types.KeyPrefixLockTimestamp), time)
}
// LockIterator returns the iterator used for getting all locks.
func (k Keeper) LockIterator(ctx sdk.Context, isUnlocking bool) sdk.Iterator {
unlockingPrefix := unlockingPrefix(isUnlocking)
return k.iterator(ctx, combineKeys(unlockingPrefix, types.KeyPrefixLockDuration))
}
// LockIteratorAfterTimeDenom returns the iterator to get locked coins by denom.
func (k Keeper) LockIteratorAfterTimeDenom(ctx sdk.Context, denom string, time time.Time) sdk.Iterator {
unlockingPrefix := unlockingPrefix(true)
return k.iteratorAfterTime(ctx, combineKeys(unlockingPrefix, types.KeyPrefixDenomLockTimestamp, []byte(denom)), time)
}
// LockIteratorBeforeTimeDenom returns the iterator to get unlockable coins by denom.
func (k Keeper) LockIteratorBeforeTimeDenom(ctx sdk.Context, denom string, time time.Time) sdk.Iterator {
unlockingPrefix := unlockingPrefix(true)
return k.iteratorBeforeTime(ctx, combineKeys(unlockingPrefix, types.KeyPrefixDenomLockTimestamp, []byte(denom)), time)
}
// LockIteratorLongerThanDurationDenom returns the iterator to get locked locks by denom.
func (k Keeper) LockIteratorLongerThanDurationDenom(ctx sdk.Context, isUnlocking bool, denom string, duration time.Duration) sdk.Iterator {
unlockingPrefix := unlockingPrefix(isUnlocking)
return k.iteratorLongerDuration(ctx, combineKeys(unlockingPrefix, types.KeyPrefixDenomLockDuration, []byte(denom)), duration)
}
// LockIteratorDenom returns the iterator used for getting all locks by denom.
func (k Keeper) LockIteratorDenom(ctx sdk.Context, isUnlocking bool, denom string) sdk.Iterator {
unlockingPrefix := unlockingPrefix(isUnlocking)
return k.iterator(ctx, combineKeys(unlockingPrefix, types.KeyPrefixDenomLockDuration, []byte(denom)))
}
// AccountLockIteratorAfterTime returns the iterator to get locked coins by account.
func (k Keeper) AccountLockIteratorAfterTime(ctx sdk.Context, addr sdk.AccAddress, time time.Time) sdk.Iterator {
unlockingPrefix := unlockingPrefix(true)
return k.iteratorAfterTime(ctx, combineKeys(unlockingPrefix, types.KeyPrefixAccountLockTimestamp, addr), time)
}
// AccountLockIteratorBeforeTime returns the iterator to get unlockable coins by account.
func (k Keeper) AccountLockIteratorBeforeTime(ctx sdk.Context, addr sdk.AccAddress, time time.Time) sdk.Iterator {
unlockingPrefix := unlockingPrefix(true)
return k.iteratorBeforeTime(ctx, combineKeys(unlockingPrefix, types.KeyPrefixAccountLockTimestamp, addr), time)
}
// AccountLockIterator returns the iterator used for getting all locks by account.
func (k Keeper) AccountLockIterator(ctx sdk.Context, isUnlocking bool, addr sdk.AccAddress) sdk.Iterator {
unlockingPrefix := unlockingPrefix(isUnlocking)
return k.iterator(ctx, combineKeys(unlockingPrefix, types.KeyPrefixAccountLockDuration, addr))
}
// AccountLockIteratorAfterTimeDenom returns the iterator to get locked coins by account and denom.
func (k Keeper) AccountLockIteratorAfterTimeDenom(ctx sdk.Context, addr sdk.AccAddress, denom string, time time.Time) sdk.Iterator {
unlockingPrefix := unlockingPrefix(true)
return k.iteratorAfterTime(ctx, combineKeys(unlockingPrefix, types.KeyPrefixAccountDenomLockTimestamp, addr, []byte(denom)), time)
}
// AccountLockIteratorBeforeTimeDenom returns the iterator to get unlockable coins by account and denom.
func (k Keeper) AccountLockIteratorBeforeTimeDenom(ctx sdk.Context, addr sdk.AccAddress, denom string, time time.Time) sdk.Iterator {
unlockingPrefix := unlockingPrefix(true)
return k.iteratorBeforeTime(ctx, combineKeys(unlockingPrefix, types.KeyPrefixAccountDenomLockTimestamp, addr, []byte(denom)), time)
}
// AccountLockIteratorDenom returns the iterator used for getting all locks by account and denom.
func (k Keeper) AccountLockIteratorDenom(ctx sdk.Context, isUnlocking bool, addr sdk.AccAddress, denom string) sdk.Iterator {
unlockingPrefix := unlockingPrefix(isUnlocking)
return k.iterator(ctx, combineKeys(unlockingPrefix, types.KeyPrefixAccountDenomLockDuration, addr, []byte(denom)))
}
// AccountLockIteratorLongerDuration returns iterator used for getting all locks by account longer than duration.
func (k Keeper) AccountLockIteratorLongerDuration(ctx sdk.Context, isUnlocking bool, addr sdk.AccAddress, duration time.Duration) sdk.Iterator {
unlockingPrefix := unlockingPrefix(isUnlocking)
return k.iteratorLongerDuration(ctx, combineKeys(unlockingPrefix, types.KeyPrefixAccountLockDuration, addr), duration)
}
// AccountLockIteratorDuration returns an iterator used for getting all locks for a given account, isUnlocking, and specific duration.
func (k Keeper) AccountLockIteratorDuration(ctx sdk.Context, isUnlocking bool, addr sdk.AccAddress, duration time.Duration) sdk.Iterator {
unlockingPrefix := unlockingPrefix(isUnlocking)
return k.iteratorDuration(ctx, combineKeys(unlockingPrefix, types.KeyPrefixAccountLockDuration, addr), duration)
}
// AccountLockIteratorShorterThanDuration returns an iterator used for getting all locks by account shorter than the specified duration.
func (k Keeper) AccountLockIteratorShorterThanDuration(ctx sdk.Context, isUnlocking bool, addr sdk.AccAddress, duration time.Duration) sdk.Iterator {
unlockingPrefix := unlockingPrefix(isUnlocking)
return k.iteratorShorterDuration(ctx, combineKeys(unlockingPrefix, types.KeyPrefixAccountLockDuration, addr), duration)
}
// AccountLockIteratorLongerDurationDenom returns iterator used for getting all locks by account and denom longer than duration.
func (k Keeper) AccountLockIteratorLongerDurationDenom(ctx sdk.Context, isUnlocking bool, addr sdk.AccAddress, denom string, duration time.Duration) sdk.Iterator {
unlockingPrefix := unlockingPrefix(isUnlocking)
return k.iteratorLongerDuration(ctx, combineKeys(unlockingPrefix, types.KeyPrefixAccountDenomLockDuration, addr, []byte(denom)), duration)
}
// AccountLockIteratorDurationDenom returns iterator used for getting all locks by account and denom with specific duration.
func (k Keeper) AccountLockIteratorDurationDenom(ctx sdk.Context, isUnlocking bool, addr sdk.AccAddress, denom string, duration time.Duration) sdk.Iterator {
unlockingPrefix := unlockingPrefix(isUnlocking)
return k.iteratorDuration(ctx, combineKeys(unlockingPrefix, types.KeyPrefixAccountDenomLockDuration, addr, []byte(denom)), duration)
}
// getLocksFromIterator returns an array of single lock unit by period defined by the x/lockup module.
func (k Keeper) getLocksFromIterator(ctx sdk.Context, iterator db.Iterator) []types.PeriodLock {
locks := []types.PeriodLock{}
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
lockID := sdk.BigEndianToUint64(iterator.Value())
lock, err := k.GetLockByID(ctx, lockID)
if err != nil {
panic(err)
}
locks = append(locks, *lock)
}
return locks
}
// unlockFromIterator gets locks from the iterator, then unlocks all matured locks. Returns locks unlocked and sum of coins unlocked.
func (k Keeper) unlockFromIterator(ctx sdk.Context, iterator db.Iterator) ([]types.PeriodLock, sdk.Coins) {
// Note: this function is only used for an account
// and this has no conflicts with synthetic lockups
coins := sdk.Coins{}
locks := k.getLocksFromIterator(ctx, iterator)
for _, lock := range locks {
err := k.UnlockMaturedLock(ctx, lock.ID)
if err != nil {
panic(err)
}
// sum up all coins unlocked
coins = coins.Add(lock.Coins...)
}
return locks, coins
}
// beginUnlockFromIterator starts unlocking coins from NotUnlocking queue.
func (k Keeper) beginUnlockFromIterator(ctx sdk.Context, iterator db.Iterator) ([]types.PeriodLock, error) {
// Note: this function is only used for an account
// and this has no conflicts with synthetic lockups
locks := k.getLocksFromIterator(ctx, iterator)
for _, lock := range locks {
_, err := k.BeginUnlock(ctx, lock.ID, nil)
if err != nil {
return locks, err
}
}
return locks, nil
}
// getCoinsFromIterator gets coins from locks using the iterator.
func (k Keeper) getCoinsFromIterator(ctx sdk.Context, iterator db.Iterator) sdk.Coins {
return k.getCoinsFromLocks(k.getLocksFromIterator(ctx, iterator))
}