get records from attributes

This commit is contained in:
0xmuralik 2022-10-13 16:40:11 +05:30
parent a43b8fee5c
commit b38e3a9106
4 changed files with 81 additions and 136 deletions

View File

@ -30,12 +30,13 @@ func (q Querier) ListRecords(c context.Context, req *types.QueryListRecordsReque
ctx := sdk.UnwrapSDKContext(c)
attributes := req.GetAttributes()
all := req.GetAll()
records := []types.Record{}
var records []types.Record
if len(attributes) > 0 {
records = q.Keeper.MatchRecords(ctx, func(record *types.RecordType) bool {
return MatchOnAttributes(record, attributes, all)
})
var err error
records, err = q.Keeper.RecordsFromAttributes(ctx, attributes, all)
if err != nil {
return nil, err
}
} else {
records = q.Keeper.ListRecords(ctx)
}
@ -113,115 +114,3 @@ func (q Querier) GetAuthorityExpiryQueue(c context.Context, _ *types.QueryGetAut
authorities := q.Keeper.GetAuthorityExpiryQueue(ctx)
return &types.QueryGetAuthorityExpiryQueueResponse{Authorities: authorities}, nil
}
func matchOnRecordField(record *types.RecordType, attr *types.QueryListRecordsRequest_KeyValueInput) (fieldFound bool, matched bool) {
fieldFound = false
matched = true
switch attr.Key {
case BondIDAttributeName:
{
fieldFound = true
if record.BondId != attr.Value.GetString_() {
matched = false
return
}
}
case ExpiryTimeAttributeName:
{
fieldFound = true
if record.ExpiryTime != attr.Value.GetString_() {
matched = false
return
}
}
}
return
}
func MatchOnAttributes(record *types.RecordType, attributes []*types.QueryListRecordsRequest_KeyValueInput, all bool) bool {
// Filter deleted records.
if record.Deleted {
return false
}
// If ONLY named records are requested, check for that condition first.
if !all && len(record.Names) == 0 {
return false
}
recAttrs := record.Attributes
for _, attr := range attributes {
// First try matching on record struct fields.
fieldFound, matched := matchOnRecordField(record, attr)
if fieldFound {
if !matched {
return false
}
continue
}
recAttrVal, recAttrFound := recAttrs[attr.Key]
if !recAttrFound {
return false
}
if attr.Value.Type == "int" {
recAttrValInt, ok := recAttrVal.(int)
if !ok || int(attr.Value.GetInt()) != recAttrValInt {
return false
}
}
if attr.Value.Type == "float" {
recAttrValFloat, ok := recAttrVal.(float64)
if !ok || attr.Value.GetFloat() != recAttrValFloat {
return false
}
}
if attr.Value.Type == "string" {
recAttrValString, ok := recAttrVal.(string)
if !ok {
return false
}
if attr.Value.GetString_() != recAttrValString {
return false
}
}
if attr.Value.Type == "boolean" {
recAttrValBool, ok := recAttrVal.(bool)
if !ok || attr.Value.GetBoolean() != recAttrValBool {
return false
}
}
if attr.Value.Type == "reference" {
obj, ok := recAttrVal.(map[string]interface{})
if !ok {
// Attr value is not an object.
return false
}
if _, ok := obj["/"].(string); !ok {
// Attr value is not a reference.
return false
}
recAttrValRefID := obj["/"].(string)
if recAttrValRefID != attr.Value.GetReference().GetId() {
return false
}
}
// TODO: Handle arrays.
}
return true
}

View File

@ -131,29 +131,61 @@ func (k Keeper) ListRecords(ctx sdk.Context) []types.Record {
return records
}
// MatchRecords - get all matching records.
func (k Keeper) MatchRecords(ctx sdk.Context, matchFn func(*types.RecordType) bool) []types.Record {
var records []types.Record
store := ctx.KVStore(k.storeKey)
itr := sdk.KVStorePrefixIterator(store, PrefixCIDToRecordIndex)
defer itr.Close()
for ; itr.Valid(); itr.Next() {
bz := store.Get(itr.Key())
if bz != nil {
var obj types.Record
k.cdc.MustUnmarshal(bz, &obj)
obj = recordObjToRecord(store, k.cdc, obj)
record := obj.ToRecordType()
if matchFn(&record) {
records = append(records, obj)
}
func (k Keeper) RecordsFromAttributes(ctx sdk.Context, attributes []*types.QueryListRecordsRequest_KeyValueInput, all bool) ([]types.Record, error) {
resultRecordIds := []string{}
for i, attr := range attributes {
attributeIndex := GetAttributesIndexKey(attr.Key, attr.Value)
recordIds, err := k.GetAttributeMapping(ctx, attributeIndex)
if err != nil {
return nil, err
}
if i == 0 {
resultRecordIds = recordIds
} else {
resultRecordIds = getIntersection(recordIds, resultRecordIds)
}
}
return records
records := []types.Record{}
for _, id := range resultRecordIds {
record := k.GetRecord(ctx, id)
if record.Deleted {
continue
}
if !all && len(record.Names) == 0 {
continue
}
records = append(records, record)
}
return records, nil
}
func getIntersection(a []string, b []string) []string {
result := []string{}
if len(a) < len(b) {
for _, str := range a {
if contains(b, str) {
result = append(result, str)
}
}
} else {
for _, str := range b {
if contains(a, str) {
result = append(result, str)
}
}
}
return result
}
func contains(arr []string, str string) bool {
for _, s := range arr {
if s == str {
return true
}
}
return false
}
func (k Keeper) GetRecordExpiryQueue(ctx sdk.Context) []*types.ExpiryQueueRecord {
var records []*types.ExpiryQueueRecord
@ -292,6 +324,9 @@ func (k Keeper) ProcessAttributes(ctx sdk.Context, record types.RecordType) erro
return fmt.Errorf("unsupported record type %s", record.Attributes["type"])
}
expiryTimeKey := GetAttributesIndexKey(ExpiryTimeAttributeName, record.ExpiryTime)
k.SetAttributeMapping(ctx, expiryTimeKey, record.Id)
return nil
}
@ -320,6 +355,22 @@ func (k Keeper) SetAttributeMapping(ctx sdk.Context, key []byte, recordId string
return nil
}
func (k Keeper) GetAttributeMapping(ctx sdk.Context, key []byte) ([]string, error) {
store := ctx.KVStore(k.storeKey)
if !store.Has(key) {
return nil, fmt.Errorf("store doesn't have key")
}
var recordIds []string
if err := json.Unmarshal(store.Get(key), &recordIds); err != nil {
return nil, fmt.Errorf("cannont unmarshal byte array, error, %w", err)
}
return recordIds, nil
}
// AddBondToRecordIndexEntry adds the Bond ID -> [Record] index entry.
func (k Keeper) AddBondToRecordIndexEntry(ctx sdk.Context, bondID string, id string) {
store := ctx.KVStore(k.storeKey)

View File

@ -161,6 +161,9 @@ func (m msgServer) DeleteName(c context.Context, msg *types.MsgDeleteNameAuthori
func (m msgServer) RenewRecord(c context.Context, msg *types.MsgRenewRecord) (*types.MsgRenewRecordResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
_, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
err = m.Keeper.ProcessRenewRecord(ctx, *msg)
if err != nil {
return nil, err
@ -264,6 +267,9 @@ func (m msgServer) ReAssociateRecords(c context.Context, msg *types.MsgReAssocia
return nil, err
}
err = m.Keeper.ProcessReAssociateRecords(ctx, *msg)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeReAssociateRecords,

View File

@ -651,7 +651,6 @@ func (k Keeper) GetAllExpiredAuthorities(ctx sdk.Context, currTime time.Time) (e
defer itr.Close()
for ; itr.Valid(); itr.Next() {
timeslice := []string{}
timeslice, err := helpers.BytesArrToStringArr(itr.Value())
if err != nil {