diff --git a/types/utils.go b/types/utils.go index dc13af6f9..50074f2b0 100644 --- a/types/utils.go +++ b/types/utils.go @@ -6,6 +6,7 @@ import ( "fmt" "time" + "github.com/cosmos/cosmos-sdk/types/kv" dbm "github.com/tendermint/tm-db" ) @@ -106,3 +107,30 @@ func CopyBytes(bz []byte) (ret []byte) { copy(ret, bz) return ret } + +// AppendLengthPrefixedBytes combines the slices of bytes to one slice of bytes. +func AppendLengthPrefixedBytes(args ...[]byte) []byte { + length := 0 + for _, v := range args { + length += len(v) + } + res := make([]byte, length) + + length = 0 + for _, v := range args { + copy(res[length:length+len(v)], v) + length += len(v) + } + + return res +} + +// ParseLengthPrefixedBytes panics when store key length is not equal to the given length. +func ParseLengthPrefixedBytes(key []byte, startIndex int, sliceLength int) ([]byte, int) { + neededLength := startIndex + sliceLength + endIndex := neededLength - 1 + kv.AssertKeyAtLeastLength(key, neededLength) + byteSlice := key[startIndex:neededLength] + + return byteSlice, endIndex +} diff --git a/types/utils_test.go b/types/utils_test.go index c04c9c81f..06576d407 100644 --- a/types/utils_test.go +++ b/types/utils_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/suite" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" ) type utilsTestSuite struct { @@ -109,3 +110,23 @@ func (s *utilsTestSuite) TestParseTimeBytes() { _, err = sdk.ParseTimeBytes([]byte{}) s.Require().Error(err) } + +func (s *utilsTestSuite) TestAppendParseBytes() { + test1 := "test1" + test2 := "testString2" + testByte1 := []byte(test1) + testByte2 := []byte(test2) + + combinedBytes := sdk.AppendLengthPrefixedBytes(address.MustLengthPrefix(testByte1), address.MustLengthPrefix(testByte2)) + testCombineBytes := append([]byte{}, address.MustLengthPrefix(testByte1)...) + testCombineBytes = append(testCombineBytes, address.MustLengthPrefix(testByte2)...) + s.Require().Equal(combinedBytes, testCombineBytes) + + test1Len, test1LenEndIndex := sdk.ParseLengthPrefixedBytes(combinedBytes, 0, 1) + parseTest1, parseTest1EndIndex := sdk.ParseLengthPrefixedBytes(combinedBytes, test1LenEndIndex+1, int(test1Len[0])) + s.Require().Equal(testByte1, parseTest1) + + test2Len, test2LenEndIndex := sdk.ParseLengthPrefixedBytes(combinedBytes, parseTest1EndIndex+1, 1) + parseTest2, _ := sdk.ParseLengthPrefixedBytes(combinedBytes, test2LenEndIndex+1, int(test2Len[0])) + s.Require().Equal(testByte2, parseTest2) +} diff --git a/x/authz/keeper/keys.go b/x/authz/keeper/keys.go index 9a935e5b2..a079b71dd 100644 --- a/x/authz/keeper/keys.go +++ b/x/authz/keeper/keys.go @@ -34,14 +34,8 @@ func grantStoreKey(grantee sdk.AccAddress, granter sdk.AccAddress, msgType strin m := conv.UnsafeStrToBytes(msgType) granter = address.MustLengthPrefix(granter) grantee = address.MustLengthPrefix(grantee) + key := sdk.AppendLengthPrefixedBytes(GrantKey, granter, grantee, m) - l := 1 + len(grantee) + len(granter) + len(m) - var key = make([]byte, l) - copy(key, GrantKey) - copy(key[1:], granter) - copy(key[1+len(granter):], grantee) - copy(key[l-len(m):], m) - // fmt.Println(">>>> len", l, key) return key } @@ -49,15 +43,15 @@ func grantStoreKey(grantee sdk.AccAddress, granter sdk.AccAddress, msgType strin func parseGrantStoreKey(key []byte) (granterAddr, granteeAddr sdk.AccAddress, msgType string) { // key is of format: // 0x01 - kv.AssertKeyAtLeastLength(key, 2) - granterAddrLen := key[1] // remove prefix key - kv.AssertKeyAtLeastLength(key, int(3+granterAddrLen)) - granterAddr = sdk.AccAddress(key[2 : 2+granterAddrLen]) - granteeAddrLen := int(key[2+granterAddrLen]) - kv.AssertKeyAtLeastLength(key, 4+int(granterAddrLen+byte(granteeAddrLen))) - granteeAddr = sdk.AccAddress(key[3+granterAddrLen : 3+granterAddrLen+byte(granteeAddrLen)]) - return granterAddr, granteeAddr, conv.UnsafeBytesToStr(key[3+granterAddrLen+byte(granteeAddrLen):]) + granterAddrLen, granterAddrLenEndIndex := sdk.ParseLengthPrefixedBytes(key, 1, 1) // ignore key[0] since it is a prefix key + granterAddr, granterAddrEndIndex := sdk.ParseLengthPrefixedBytes(key, granterAddrLenEndIndex+1, int(granterAddrLen[0])) + + granteeAddrLen, granteeAddrLenEndIndex := sdk.ParseLengthPrefixedBytes(key, granterAddrEndIndex+1, 1) + granteeAddr, granteeAddrEndIndex := sdk.ParseLengthPrefixedBytes(key, granteeAddrLenEndIndex+1, int(granteeAddrLen[0])) + + kv.AssertKeyAtLeastLength(key, granteeAddrEndIndex+1) + return granterAddr, granteeAddr, conv.UnsafeBytesToStr(key[(granteeAddrEndIndex + 1):]) } // parseGrantQueueKey split expiration time, granter and grantee from the grant queue key @@ -65,20 +59,18 @@ func parseGrantQueueKey(key []byte) (time.Time, sdk.AccAddress, sdk.AccAddress, // key is of format: // 0x02 - kv.AssertKeyAtLeastLength(key, 1+lenTime) - exp, err := sdk.ParseTimeBytes(key[1 : 1+lenTime]) + expBytes, expEndIndex := sdk.ParseLengthPrefixedBytes(key, 1, lenTime) + + exp, err := sdk.ParseTimeBytes(expBytes) if err != nil { return exp, nil, nil, err } - granterAddrLen := key[1+lenTime] - kv.AssertKeyAtLeastLength(key, 1+lenTime+int(granterAddrLen)) - granter := sdk.AccAddress(key[2+lenTime : byte(2+lenTime)+granterAddrLen]) + granterAddrLen, granterAddrLenEndIndex := sdk.ParseLengthPrefixedBytes(key, expEndIndex+1, 1) + granter, granterEndIndex := sdk.ParseLengthPrefixedBytes(key, granterAddrLenEndIndex+1, int(granterAddrLen[0])) - granteeAddrLen := key[byte(2+lenTime)+granterAddrLen] - granteeStart := byte(3+lenTime) + granterAddrLen - kv.AssertKeyAtLeastLength(key, int(granteeStart)) - grantee := sdk.AccAddress(key[granteeStart : granteeStart+granteeAddrLen]) + granteeAddrLen, granteeAddrLenEndIndex := sdk.ParseLengthPrefixedBytes(key, granterEndIndex+1, 1) + grantee, _ := sdk.ParseLengthPrefixedBytes(key, granteeAddrLenEndIndex+1, int(granteeAddrLen[0])) return exp, granter, grantee, nil } @@ -92,13 +84,7 @@ func GrantQueueKey(expiration time.Time, granter sdk.AccAddress, grantee sdk.Acc granter = address.MustLengthPrefix(granter) grantee = address.MustLengthPrefix(grantee) - l := 1 + len(exp) + len(granter) + len(grantee) - var key = make([]byte, l) - copy(key, GrantQueuePrefix) - copy(key[1:], exp) - copy(key[1+len(exp):], granter) - copy(key[1+len(exp)+len(granter):], grantee) - return key + return sdk.AppendLengthPrefixedBytes(GrantQueuePrefix, exp, granter, grantee) } // GrantQueueTimePrefix - return grant queue time prefix