Add a command to set name

This commit is contained in:
Prathamesh Musale 2024-02-19 18:59:32 +05:30
parent 5527c91c19
commit 9ee1f315a1
6 changed files with 189 additions and 7 deletions

View File

@ -61,6 +61,26 @@ func newAuthorityIndexes(sb *collections.SchemaBuilder) AuthoritiesIndexes {
return AuthoritiesIndexes{}
}
type NameRecordsIndexes struct {
Cid *indexes.Multi[string, string, registrytypes.NameRecord]
}
func (b NameRecordsIndexes) IndexesList() []collections.Index[string, registrytypes.NameRecord] {
return []collections.Index[string, registrytypes.NameRecord]{b.Cid}
}
func newNameRecordIndexes(sb *collections.SchemaBuilder) NameRecordsIndexes {
return NameRecordsIndexes{
Cid: indexes.NewMulti(
sb, registrytypes.NameRecordsByCidIndexPrefix, "name_records_by_cid",
collections.StringKey, collections.StringKey,
func(_ string, v registrytypes.NameRecord) (string, error) {
return v.Latest.Id, nil
},
),
}
}
type Keeper struct {
cdc codec.BinaryCodec
@ -75,6 +95,7 @@ type Keeper struct {
Params collections.Item[registrytypes.Params]
Records *collections.IndexedMap[string, registrytypes.Record, RecordsIndexes]
Authorities *collections.IndexedMap[string, registrytypes.NameAuthority, AuthoritiesIndexes]
NameRecords *collections.IndexedMap[string, registrytypes.NameRecord, NameRecordsIndexes]
}
// NewKeeper creates a new Keeper instance
@ -106,6 +127,11 @@ func NewKeeper(
collections.StringKey, codec.CollValue[registrytypes.NameAuthority](cdc),
newAuthorityIndexes(sb),
),
NameRecords: collections.NewIndexedMap(
sb, registrytypes.NameRecordsPrefix, "name_records",
collections.StringKey, codec.CollValue[registrytypes.NameRecord](cdc),
newNameRecordIndexes(sb),
),
}
schema, err := sb.Build()

View File

@ -51,14 +51,17 @@ func (ms msgServer) SetRecord(c context.Context, msg *registrytypes.MsgSetRecord
// nolint: all
func (ms msgServer) SetName(c context.Context, msg *registrytypes.MsgSetName) (*registrytypes.MsgSetNameResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
_, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
err = ms.k.ProcessSetName(ctx, *msg)
err = ms.k.SetName(ctx, *msg)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
registrytypes.EventTypeSetRecord,

View File

@ -45,8 +45,40 @@ func (k Keeper) HasNameRecord(ctx sdk.Context, crn string) bool {
}
// GetNameRecord - gets a name record from the store.
func (k Keeper) GetNameRecord(ctx sdk.Context, crn string) *registrytypes.NameRecord {
panic("unimplemented")
func (k Keeper) GetNameRecord(ctx sdk.Context, crn string) (*registrytypes.NameRecord, error) {
nameRecord, err := k.NameRecords.Get(ctx, crn)
if err != nil {
if errors.Is(err, collections.ErrNotFound) {
return nil, nil
}
return nil, err
}
return &nameRecord, nil
}
// LookupNameRecord - gets a name record which is not stale and under active authority.
func (k Keeper) LookupNameRecord(ctx sdk.Context, crn string) (*registrytypes.NameRecord, error) {
_, _, authority, err := k.getAuthority(ctx, crn)
if err != nil || authority.Status != registrytypes.AuthorityActive {
// If authority is not active (or any other error), lookup fails.
return nil, nil
}
nameRecord, err := k.GetNameRecord(ctx, crn)
// Name record may not exist.
if nameRecord == nil {
return nil, err
}
// Name lookup should fail if the name record is stale.
// i.e. authority was registered later than the name.
if authority.Height > nameRecord.Latest.Height {
return nil, nil
}
return nameRecord, nil
}
// ListNameRecords - get all name records.
@ -54,9 +86,56 @@ func (k Keeper) ListNameRecords(ctx sdk.Context) []registrytypes.NameEntry {
panic("unimplemented")
}
// ProcessSetName creates a CRN -> Record ID mapping.
func (k Keeper) ProcessSetName(ctx sdk.Context, msg registrytypes.MsgSetName) error {
panic("unimplemented")
// SaveNameRecord - sets a name record.
func (k Keeper) SaveNameRecord(ctx sdk.Context, crn string, id string) error {
var nameRecord registrytypes.NameRecord
x, err := k.GetNameRecord(ctx, crn)
if err != nil {
return err
}
if x != nil {
nameRecord = *x
nameRecord.History = append(nameRecord.History, nameRecord.Latest)
}
nameRecord.Latest = &registrytypes.NameRecordEntry{
Id: id,
Height: uint64(ctx.BlockHeight()),
}
// TODO: Check if index gets updated on entry updates
if err := k.NameRecords.Set(ctx, crn, nameRecord); err != nil {
return err
}
// TODO
// Update changeSet for name.
// k.updateBlockChangeSetForName(ctx, crn)
return nil
}
// SetName creates a CRN -> Record ID mapping.
func (k Keeper) SetName(ctx sdk.Context, msg registrytypes.MsgSetName) error {
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return err
}
err = k.checkCRNAccess(ctx, signerAddress, msg.Crn)
if err != nil {
return err
}
nameRecord, err := k.LookupNameRecord(ctx, msg.Crn)
if err != nil {
return err
}
if nameRecord != nil && nameRecord.Latest.Id == msg.Cid {
return nil
}
return k.SaveNameRecord(ctx, msg.Crn, msg.Cid)
}
// SaveNameAuthority creates the NameAuthority record.
@ -253,6 +332,68 @@ func (k Keeper) ResolveCRN(ctx sdk.Context, crn string) *registrytypes.Record {
panic("unimplemented")
}
func (k Keeper) getAuthority(ctx sdk.Context, crn string) (string, *url.URL, *registrytypes.NameAuthority, error) {
parsedCRN, err := url.Parse(crn)
if err != nil {
return "", nil, nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Invalid CRN.")
}
name := parsedCRN.Host
if has, err := k.HasNameAuthority(ctx, name); !has {
if err != nil {
return "", nil, nil, err
}
return "", nil, nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Name authority not found.")
}
authority, err := k.GetNameAuthority(ctx, name)
if err != nil {
return "", nil, nil, err
}
return name, parsedCRN, &authority, nil
}
func (k Keeper) checkCRNAccess(ctx sdk.Context, signer sdk.AccAddress, crn string) error {
name, parsedCRN, authority, err := k.getAuthority(ctx, crn)
if err != nil {
return err
}
formattedCRN := fmt.Sprintf("crn://%s%s", name, parsedCRN.RequestURI())
if formattedCRN != crn {
return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Invalid CRN.")
}
if authority.OwnerAddress != signer.String() {
return errorsmod.Wrap(sdkerrors.ErrUnauthorized, "Access denied.")
}
if authority.Status != registrytypes.AuthorityActive {
return errorsmod.Wrap(sdkerrors.ErrUnauthorized, "Authority is not active.")
}
if authority.BondId == "" || len(authority.BondId) == 0 {
return errorsmod.Wrap(sdkerrors.ErrUnauthorized, "Authority bond not found.")
}
if authority.OwnerPublicKey == "" {
// Try to set owner public key if account has it available now.
ownerAccount := k.accountKeeper.GetAccount(ctx, signer)
pubKey := ownerAccount.GetPubKey()
if pubKey != nil {
// Update public key in authority record.
authority.OwnerPublicKey = getAuthorityPubKey(pubKey)
if err = k.SaveNameAuthority(ctx, name, authority); err != nil {
return err
}
}
}
return nil
}
func getAuthorityPubKey(pubKey cryptotypes.PubKey) string {
if pubKey == nil {
return ""

View File

@ -121,7 +121,7 @@ func (qs queryServer) LookupCrn(c context.Context, req *registrytypes.QueryLooku
if !qs.k.HasNameRecord(ctx, crn) {
return nil, errorsmod.Wrap(sdkerrors.ErrUnknownRequest, "CRN not found.")
}
nameRecord := qs.k.GetNameRecord(ctx, crn)
nameRecord, _ := qs.k.LookupNameRecord(ctx, crn)
if nameRecord == nil {
return nil, errorsmod.Wrap(sdkerrors.ErrUnknownRequest, "name record not found.")
}

View File

@ -24,4 +24,7 @@ var (
AuthoritiesPrefix = collections.NewPrefix(3)
AuthoritiesByAuctionIdIndexPrefix = collections.NewPrefix(4)
AuthoritiesByBondIdIndexPrefix = collections.NewPrefix(5)
NameRecordsPrefix = collections.NewPrefix(6)
NameRecordsByCidIndexPrefix = collections.NewPrefix(7)
)

View File

@ -80,6 +80,15 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
{ProtoField: "bond_id"},
},
},
{
RpcMethod: "SetName",
Use: "set-name [crn] [cid]",
Short: "Set CRN to CID mapping",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "crn"},
{ProtoField: "cid"},
},
},
},
EnhanceCustomCommand: true, // Allow additional manual commands
},