Gogoproto
我们鼓励各模块为各自类型使用 Protobuf 编码。在 Cosmos SDK 中,我们使用 Gogoproto 对 Protobuf 规范的特定实现,相比官方的 Google protobuf 实现,它在性能和开发体验上都有所提升。protobuf 消息定义指南
除了遵循官方 Protocol Buffer 指南之外,我们还建议在处理接口时,在.proto 文件中使用以下注解:
- 对接受接口的
Any字段,使用cosmos_proto.accepts_interface进行注解:- 向
InterfaceRegistry.RegisterInterface传入与protoName相同的完整限定名。 - 示例:
(cosmos_proto.accepts_interface) = "cosmos.gov.v1beta1.Content"(而不只是Content)。
- 向
- 使用
cosmos_proto.implements_interface标注接口实现:- 向
InterfaceRegistry.RegisterInterface传入与protoName相同的完整限定名。 - 示例:
(cosmos_proto.implements_interface) = "cosmos.authz.v1beta1.Authorization"(而不只是Authorization)。
- 向
accepts_interface 与 implements_interface 注解,以判断某些 Protobuf 消息是否允许被打包进指定的 Any 字段中。
签名者
Signer 用于指定 Cosmos SDK 应当使用哪个字段来确定消息的签名者。客户端也可以使用该字段来推断应通过哪个字段确定消息签名者。
在这里了解更多关于 signer 字段的信息。
标量
Scalar 类型为客户端提供了一种方式,使其能够理解应如何按照模块和 SDK 的预期构造 protobuf 消息。
Dec 标量示例:
Int 标量示例:
cosmos.AddressString、cosmos.ValidatorAddressString、cosmos.ConsensusAddressString、cosmos.Int、cosmos.Dec。
Implements_Interface
Implement interface 用于向客户端工具(例如 telescope)提供如何对 protobuf 消息进行编码和解码的信息。
Method、Field、Message Added In
method_added_in、field_added_in 和 message_added_in 是用于告知客户端某个方法、字段或消息从较晚版本开始受支持的注解。当新方法或字段在后续版本中加入时,这对客户端了解自己可以调用哪些能力非常有用。
这些注解的使用方式如下:
Amino
Amino 编解码器已在v0.50+ 中移除,这意味着不再需要注册 legacyAminoCodec。为了替代 amino 编解码器,现在使用 Amino protobuf 注解向 amino 编解码器提供如何对 protobuf 消息进行编码和解码的信息。
Amino 注解仅用于保持与 amino 的向后兼容。新模块不要求使用 amino 注解。
名称
Name 指定向用户显示的 amino 名称,以便用户了解自己正在签署哪条消息。
字段名称
Field name 指定向用户显示的 amino 字段名称,以便用户了解自己正在签署哪个字段。
不省略空值
Dont omitempty 指定在编码为 amino 时不应省略该字段。
编码
Encoding 用于指示 amino JSON marshaler 如何对某些可能不同于标准编码行为的字段进行编码。最常见的例子是,在使用 amino JSON 编码格式时,repeated cosmos.base.v1beta1.Coin 的编码方式。legacy_coins 选项会告诉 JSON marshaler 如何对 cosmos.base.v1beta1.Coin 的空切片进行编码。
模块查询安全
cosmos.query.v1.module_query_safe 注解(源码)用于将某个查询方法标记为可在状态机内部安全调用,例如从其他模块的 keeper 中、通过 ADR-033 模块间调用,或从 CosmWasm 合约中调用。
true 时,表示该查询满足以下条件:
- 确定性:在给定区块高度的情况下,每次调用都会返回完全相同的响应,并且不会在 SDK 补丁版本之间引入破坏状态机的一致性变化。
- Gas 可追踪:Gas 消耗会被正确计量,从而避免高计算量查询不消耗 Gas 的攻击向量。
This document explains the various protobuf scalars that have been added to make working with protobuf easier for Cosmos SDK application developers
Gogoproto
Modules are encouraged to utilize Protobuf encoding for their respective types. In the Cosmos SDK, we use the Gogoproto specific implementation of the Protobuf spec that offers speed and developer experience improvements compared to the official Google protobuf implementation.Guidelines for protobuf message definitions
In addition to following official Protocol Buffer guidelines, we recommend using these annotations in.proto files when dealing with interfaces:
- Use
cosmos_proto.accepts_interfaceto annotateAnyfields that accept interfaces:- Pass the same fully qualified name as
protoNametoInterfaceRegistry.RegisterInterface. - Example:
(cosmos_proto.accepts_interface) = "cosmos.gov.v1beta1.Content"(not justContent).
- Pass the same fully qualified name as
- Annotate interface implementations with
cosmos_proto.implements_interface:- Pass the same fully qualified name as
protoNametoInterfaceRegistry.RegisterInterface. - Example:
(cosmos_proto.implements_interface) = "cosmos.authz.v1beta1.Authorization"(not justAuthorization).
- Pass the same fully qualified name as
accepts_interface and implements_interface annotations to determine whether some Protobuf messages are allowed to be packed in a given Any field.
Signer
Signer specifies which field should be used to determine the signer of a message for the Cosmos SDK. This field can be used for clients as well to infer which field should be used to determine the signer of a message. Read more about the signer field here.Scalar
The scalar type defines a way for clients to understand how to construct protobuf messages according to what is expected by the module and sdk.cosmos.AddressString, cosmos.ValidatorAddressString, cosmos.ConsensusAddressString, cosmos.Int, cosmos.Dec.
Implements_Interface
Implement interface is used to provide information to client tooling like telescope on how to encode and decode protobuf messages.Method,Field,Message Added In
method_added_in, field_added_in and message_added_in are annotations to indicate to clients that a method, field, or message has been supported since a later version. This is useful when new methods or fields are added in later versions and the client needs to be aware of what it can call.
The annotations are used as follows:
Amino
The amino codec was removed inv0.50+, this means there is not a need register legacyAminoCodec. To replace the amino codec, Amino protobuf annotations are used to provide information to the amino codec on how to encode and decode protobuf messages.
Amino annotations are only used for backwards compatibility with amino. New modules are not required use amino annotations.
Name
Name specifies the amino name that would show up for the user in order for them see which message they are signing.Field_Name
Field name specifies the amino name that would show up for the user in order for them see which field they are signing.Dont_OmitEmpty
Dont omitempty specifies that the field should not be omitted when encoding to amino.Encoding
Encoding instructs the amino json marshaler how to encode certain fields that may differ from the standard encoding behavior. The most common example of this is howrepeated cosmos.base.v1beta1.Coin is encoded when using the amino json encoding format. The legacy_coins option tells the json marshaler how to encode a null slice of cosmos.base.v1beta1.Coin.
Module Query Safe
Thecosmos.query.v1.module_query_safe annotation (source) marks a query method as safe to call from within the state machine — for example from another module’s keeper, via ADR-033 intermodule calls, or from CosmWasm contracts.
true, the annotation asserts that the query is:
- Deterministic: given a block height, it returns the exact same response on every call and does not introduce state-machine-breaking changes across SDK patch versions.
- Gas-tracked: gas consumption is correctly accounted for, preventing attack vectors where high-computation queries consume no gas.