Cosmos-- 三.教程 -- 6.SetName

cosmos主网即将上线,对文档做了大量更新。特地翻译了一下,方便小伙伴们阅览, 之后会持续更新

第三章教程:

  1. 开始
  2. 程序目标
  3. 开始编写你的程序
  4. Keeper
  5. Msg和Handler
  6. SetName
  7. BuyName
  8. Querier
  9. Codec文件
  10. Nameservice模块的CLI
  11. nameservice模块的REST接口
  12. 引入你的模块并完成程序
  13. Entrypoint
  14. 编译你的程序
  15. 编译并运行程序
  16. 运行REST路由

SetName

Msg

SDK中Msg的命令约束是 Msg{.Action}。要实现的第一个操作是SetName,因此命名为MsgSetName。此Msg允许域名的所有者设置该域名的解析返回值。首先在名为./x/nameservice/msgs.go的新文件中定义MsgSetName

package nameservice

import (
    "encoding/json"

    sdk "github.com/cosmos/cosmos-sdk/types"
)

// MsgSetName defines a SetName message
type MsgSetName struct {
    Name string
    Value  string
    Owner  sdk.AccAddress
}

// NewMsgSetName is a constructor function for MsgSetName
func NewMsgSetName(name string, value string, owner sdk.AccAddress) MsgSetName {
    return MsgSetName{
        Name: name,
        Value:  value,
        Owner:  owner,
    }
}

MsgSetName具有设置域名解析值所需的三个属性:

  • name - 所要设置的域名
  • value - 要设置的域名解析值
  • owner - 域名的所有者

接下来,实现Msg接口:

// Type should return the name of the module
func (msg MsgSetName) Route() string { return "nameservice" }

// Name should return the action
func (msg MsgSetName) Type() string { return "set_name"}

SDK使用上述函数将Msg路由至合适的模块进行处理。它们还为用于索引的数据库标签添加了可读性的名称。

// ValdateBasic Implements Msg.
func (msg MsgSetName) ValidateBasic() sdk.Error {
    if msg.Owner.Empty() {
        return sdk.ErrInvalidAddress(msg.Owner.String())
    }
    if len(msg.Name) == 0 || len(msg.Value) == 0 {
        return sdk.ErrUnknownRequest("Name and/or Value cannot be empty")
    }
    return nil
}

ValidateBasic用于对Msg的有效性进行一些基本的无状态检查。在此情形下,请检查没有属性为空。请注意这里使用sdk.Error类型。 SDK提供了一组应用开发人员经常遇到的错误类型。

// GetSignBytes Implements Msg.
func (msg MsgSetName) GetSignBytes() []byte {
    b, err := json.Marshal(msg)
    if err != nil {
        panic(err)
    }
    return sdk.MustSortJSON(b)
}

GetSignBytes定义了如何编码Msg以进行签名。在大多数情形下,要编码成排好序的JSON。不应修改输出。

// GetSigners Implements Msg.
func (msg MsgSetName) GetSigners() []sdk.AccAddress {
    return []sdk.AccAddress{msg.Owner}
}

GetSigners定义一个Tx上需要哪些人的签名才能使其有效。在这种情形下,MsgSetName要求域名所有者在尝试重置域名解析值时要对该交易签名。

Handler

现在MsgSetName已经定义好了,下一部来定义收到此Msg时需要采取的操作。也就是handler所要做的。

在一个新文件(./x/nameservice/handler.go)先写入如下代码:

package nameservice

import (
    "fmt"

    sdk "github.com/cosmos/cosmos-sdk/types"
)

// NewHandler returns a handler for "nameservice" type messages.
func NewHandler(keeper Keeper) sdk.Handler {
    return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
        switch msg := msg.(type) {
        case MsgSetName:
            return handleMsgSetName(ctx, keeper, msg)
        default:
            errMsg := fmt.Sprintf("Unrecognized nameservice Msg type: %v", msg.Type())
            return sdk.ErrUnknownRequest(errMsg).Result()
        }
    }
}

NewHandler本质上是一个子路由,它将进入该模块的msg路由到正确的handler做处理。目前,只有一个 Msg/Handler

现在,你需要定义在handlerMsgSetName中定义处理MsgSetName消息的实际逻辑:

注意:SDK中handler的命名规范是handlerMsg{.Action}

// Handle MsgSetName
func handleMsgSetName(ctx sdk.Context, keeper Keeper, msg MsgSetName) sdk.Result {
    if !msg.Owner.Equals(keeper.GetOwner(ctx, msg.Name)) { // Checks if the the msg sender is the same as the current owner
        return sdk.ErrUnauthorized("Incorrect Owner").Result() // If not, throw an error
    }
    keeper.SetName(ctx, msg.Name, msg.Value) // If so, set the name to the value specified in the msg.
    return sdk.Result{}                      // return
}

在此函数中,要检查Msg的发送者是否就是域名的所有者(keeper.GetOwner)。如果是,就能通过调用Keeper里的函数来设置域名。如果不是,则抛出错误并返回给用户。

你可能感兴趣的:(Cosmos-- 三.教程 -- 6.SetName)