github.com/cosmos/cosmos-sdk@v0.50.10/x/group/internal/orm/sequence.go (about) 1 package orm 2 3 import ( 4 "encoding/binary" 5 6 errorsmod "cosmossdk.io/errors" 7 "cosmossdk.io/store/prefix" 8 storetypes "cosmossdk.io/store/types" 9 10 "github.com/cosmos/cosmos-sdk/x/group/errors" 11 ) 12 13 // sequenceStorageKey is a fix key to read/ write data on the storage layer 14 var sequenceStorageKey = []byte{0x1} 15 16 // sequence is a persistent unique key generator based on a counter. 17 type Sequence struct { 18 prefix byte 19 } 20 21 func NewSequence(prefix byte) Sequence { 22 return Sequence{ 23 prefix: prefix, 24 } 25 } 26 27 // NextVal increments and persists the counter by one and returns the value. 28 func (s Sequence) NextVal(store storetypes.KVStore) uint64 { 29 pStore := prefix.NewStore(store, []byte{s.prefix}) 30 v := pStore.Get(sequenceStorageKey) 31 seq := DecodeSequence(v) 32 seq++ 33 pStore.Set(sequenceStorageKey, EncodeSequence(seq)) 34 return seq 35 } 36 37 // CurVal returns the last value used. 0 if none. 38 func (s Sequence) CurVal(store storetypes.KVStore) uint64 { 39 pStore := prefix.NewStore(store, []byte{s.prefix}) 40 v := pStore.Get(sequenceStorageKey) 41 return DecodeSequence(v) 42 } 43 44 // PeekNextVal returns the CurVal + increment step. Not persistent. 45 func (s Sequence) PeekNextVal(store storetypes.KVStore) uint64 { 46 pStore := prefix.NewStore(store, []byte{s.prefix}) 47 v := pStore.Get(sequenceStorageKey) 48 return DecodeSequence(v) + 1 49 } 50 51 // InitVal sets the start value for the sequence. It must be called only once on an empty DB. 52 // Otherwise an error is returned when the key exists. The given start value is stored as current 53 // value. 54 // 55 // It is recommended to call this method only for a sequence start value other than `1` as the 56 // method consumes unnecessary gas otherwise. A scenario would be an import from genesis. 57 func (s Sequence) InitVal(store storetypes.KVStore, seq uint64) error { 58 pStore := prefix.NewStore(store, []byte{s.prefix}) 59 if pStore.Has(sequenceStorageKey) { 60 return errorsmod.Wrap(errors.ErrORMUniqueConstraint, "already initialized") 61 } 62 pStore.Set(sequenceStorageKey, EncodeSequence(seq)) 63 return nil 64 } 65 66 // DecodeSequence converts the binary representation into an Uint64 value. 67 func DecodeSequence(bz []byte) uint64 { 68 if bz == nil { 69 return 0 70 } 71 val := binary.BigEndian.Uint64(bz) 72 return val 73 } 74 75 // EncodedSeqLength number of bytes used for the binary representation of a sequence value. 76 const EncodedSeqLength = 8 77 78 // EncodeSequence converts the sequence value into the binary representation. 79 func EncodeSequence(val uint64) []byte { 80 bz := make([]byte, EncodedSeqLength) 81 binary.BigEndian.PutUint64(bz, val) 82 return bz 83 }