github.com/cosmos/cosmos-sdk@v0.50.10/docs/architecture/adr-023-protobuf-naming.md (about) 1 # ADR 023: Protocol Buffer Naming and Versioning Conventions 2 3 ## Changelog 4 5 * 2020 April 27: Initial Draft 6 * 2020 August 5: Update guidelines 7 8 ## Status 9 10 Accepted 11 12 ## Context 13 14 Protocol Buffers provide a basic [style guide](https://developers.google.com/protocol-buffers/docs/style) 15 and [Buf](https://buf.build/docs/style-guide) builds upon that. To the 16 extent possible, we want to follow industry accepted guidelines and wisdom for 17 the effective usage of protobuf, deviating from those only when there is clear 18 rationale for our use case. 19 20 ### Adoption of `Any` 21 22 The adoption of `google.protobuf.Any` as the recommended approach for encoding 23 interface types (as opposed to `oneof`) makes package naming a central part 24 of the encoding as fully-qualified message names now appear in encoded 25 messages. 26 27 ### Current Directory Organization 28 29 Thus far we have mostly followed [Buf's](https://buf.build) [DEFAULT](https://buf.build/docs/lint-checkers#default) 30 recommendations, with the minor deviation of disabling [`PACKAGE_DIRECTORY_MATCH`](https://buf.build/docs/lint-checkers#file_layout) 31 which although being convenient for developing code comes with the warning 32 from Buf that: 33 34 > you will have a very bad time with many Protobuf plugins across various languages if you do not do this 35 36 ### Adoption of gRPC Queries 37 38 In [ADR 021](adr-021-protobuf-query-encoding.md), gRPC was adopted for Protobuf 39 native queries. The full gRPC service path thus becomes a key part of ABCI query 40 path. In the future, gRPC queries may be allowed from within persistent scripts 41 by technologies such as CosmWasm and these query routes would be stored within 42 script binaries. 43 44 ## Decision 45 46 The goal of this ADR is to provide thoughtful naming conventions that: 47 48 * encourage a good user experience for when users interact directly with 49 .proto files and fully-qualified protobuf names 50 * balance conciseness against the possibility of either over-optimizing (making 51 names too short and cryptic) or under-optimizing (just accepting bloated names 52 with lots of redundant information) 53 54 These guidelines are meant to act as a style guide for both the Cosmos SDK and 55 third-party modules. 56 57 As a starting point, we should adopt all of the [DEFAULT](https://buf.build/docs/lint-checkers#default) 58 checkers in [Buf's](https://buf.build) including [`PACKAGE_DIRECTORY_MATCH`](https://buf.build/docs/lint-checkers#file_layout), 59 except: 60 61 * [PACKAGE_VERSION_SUFFIX](https://buf.build/docs/lint-checkers#package_version_suffix) 62 * [SERVICE_SUFFIX](https://buf.build/docs/lint-checkers#service_suffix) 63 64 Further guidelines to be described below. 65 66 ### Principles 67 68 #### Concise and Descriptive Names 69 70 Names should be descriptive enough to convey their meaning and distinguish 71 them from other names. 72 73 Given that we are using fully-qualifed names within 74 `google.protobuf.Any` as well as within gRPC query routes, we should aim to 75 keep names concise, without going overboard. The general rule of thumb should 76 be if a shorter name would convey more or else the same thing, pick the shorter 77 name. 78 79 For instance, `cosmos.bank.MsgSend` (19 bytes) conveys roughly the same information 80 as `cosmos_sdk.x.bank.v1.MsgSend` (28 bytes) but is more concise. 81 82 Such conciseness makes names both more pleasant to work with and take up less 83 space within transactions and on the wire. 84 85 We should also resist the temptation to over-optimize, by making names 86 cryptically short with abbreviations. For instance, we shouldn't try to 87 reduce `cosmos.bank.MsgSend` to `csm.bk.MSnd` just to save a few bytes. 88 89 The goal is to make names **_concise but not cryptic_**. 90 91 #### Names are for Clients First 92 93 Package and type names should be chosen for the benefit of users, not 94 necessarily because of legacy concerns related to the go code-base. 95 96 #### Plan for Longevity 97 98 In the interests of long-term support, we should plan on the names we do 99 choose to be in usage for a long time, so now is the opportunity to make 100 the best choices for the future. 101 102 ### Versioning 103 104 #### Guidelines on Stable Package Versions 105 106 In general, schema evolution is the way to update protobuf schemas. That means that new fields, 107 messages, and RPC methods are _added_ to existing schemas and old fields, messages and RPC methods 108 are maintained as long as possible. 109 110 Breaking things is often unacceptable in a blockchain scenario. For instance, immutable smart contracts 111 may depend on certain data schemas on the host chain. If the host chain breaks those schemas, the smart 112 contract may be irreparably broken. Even when things can be fixed (for instance in client software), 113 this often comes at a high cost. 114 115 Instead of breaking things, we should make every effort to evolve schemas rather than just breaking them. 116 [Buf](https://buf.build) breaking change detection should be used on all stable (non-alpha or beta) packages 117 to prevent such breakage. 118 119 With that in mind, different stable versions (i.e. `v1` or `v2`) of a package should more or less be considered 120 different packages and this should be last resort approach for upgrading protobuf schemas. Scenarios where creating 121 a `v2` may make sense are: 122 123 * we want to create a new module with similar functionality to an existing module and adding `v2` is the most natural 124 way to do this. In that case, there are really just two different, but similar modules with different APIs. 125 * we want to add a new revamped API for an existing module and it's just too cumbersome to add it to the existing package, 126 so putting it in `v2` is cleaner for users. In this case, care should be made to not deprecate support for 127 `v1` if it is actively used in immutable smart contracts. 128 129 #### Guidelines on unstable (alpha and beta) package versions 130 131 The following guidelines are recommended for marking packages as alpha or beta: 132 133 * marking something as `alpha` or `beta` should be a last resort and just putting something in the 134 stable package (i.e. `v1` or `v2`) should be preferred 135 * a package _should_ be marked as `alpha` _if and only if_ there are active discussions to remove 136 or significantly alter the package in the near future 137 * a package _should_ be marked as `beta` _if and only if_ there is an active discussion to 138 significantly refactor/rework the functionality in the near future but not remove it 139 * modules _can and should_ have types in both stable (i.e. `v1` or `v2`) and unstable (`alpha` or `beta`) packages. 140 141 _`alpha` and `beta` should not be used to avoid responsibility for maintaining compatibility._ 142 Whenever code is released into the wild, especially on a blockchain, there is a high cost to changing things. In some 143 cases, for instance with immutable smart contracts, a breaking change may be impossible to fix. 144 145 When marking something as `alpha` or `beta`, maintainers should ask the questions: 146 147 * what is the cost of asking others to change their code vs the benefit of us maintaining the optionality to change it? 148 * what is the plan for moving this to `v1` and how will that affect users? 149 150 `alpha` or `beta` should really be used to communicate "changes are planned". 151 152 As a case study, gRPC reflection is in the package `grpc.reflection.v1alpha`. It hasn't been changed since 153 2017 and it is now used in other widely used software like gRPCurl. Some folks probably use it in production services 154 and so if they actually went and changed the package to `grpc.reflection.v1`, some software would break and 155 they probably don't want to do that... So now the `v1alpha` package is more or less the de-facto `v1`. Let's not do that. 156 157 The following are guidelines for working with non-stable packages: 158 159 * [Buf's recommended version suffix](https://buf.build/docs/lint-checkers#package_version_suffix) 160 (ex. `v1alpha1`) _should_ be used for non-stable packages 161 * non-stable packages should generally be excluded from breaking change detection 162 * immutable smart contract modules (i.e. CosmWasm) _should_ block smart contracts/persistent 163 scripts from interacting with `alpha`/`beta` packages 164 165 #### Omit v1 suffix 166 167 Instead of using [Buf's recommended version suffix](https://buf.build/docs/lint-checkers#package_version_suffix), 168 we can omit `v1` for packages that don't actually have a second version. This 169 allows for more concise names for common use cases like `cosmos.bank.Send`. 170 Packages that do have a second or third version can indicate that with `.v2` 171 or `.v3`. 172 173 ### Package Naming 174 175 #### Adopt a short, unique top-level package name 176 177 Top-level packages should adopt a short name that is known to not collide with 178 other names in common usage within the Cosmos ecosystem. In the near future, a 179 registry should be created to reserve and index top-level package names used 180 within the Cosmos ecosystem. Because the Cosmos SDK is intended to provide 181 the top-level types for the Cosmos project, the top-level package name `cosmos` 182 is recommended for usage within the Cosmos SDK instead of the longer `cosmos_sdk`. 183 [ICS](https://github.com/cosmos/ics) specifications could consider a 184 short top-level package like `ics23` based upon the standard number. 185 186 #### Limit sub-package depth 187 188 Sub-package depth should be increased with caution. Generally a single 189 sub-package is needed for a module or a library. Even though `x` or `modules` 190 is used in source code to denote modules, this is often unnecessary for .proto 191 files as modules are the primary thing sub-packages are used for. Only items which 192 are known to be used infrequently should have deep sub-package depths. 193 194 For the Cosmos SDK, it is recommended that we simply write `cosmos.bank`, 195 `cosmos.gov`, etc. rather than `cosmos.x.bank`. In practice, most non-module 196 types can go straight in the `cosmos` package or we can introduce a 197 `cosmos.base` package if needed. Note that this naming _will not_ change 198 go package names, i.e. the `cosmos.bank` protobuf package will still live in 199 `x/bank`. 200 201 ### Message Naming 202 203 Message type names should be as concise possible without losing clarity. `sdk.Msg` 204 types which are used in transactions will retain the `Msg` prefix as that provides 205 helpful context. 206 207 ### Service and RPC Naming 208 209 [ADR 021](adr-021-protobuf-query-encoding.md) specifies that modules should 210 implement a gRPC query service. We should consider the principle of conciseness 211 for query service and RPC names as these may be called from persistent script 212 modules such as CosmWasm. Also, users may use these query paths from tools like 213 [gRPCurl](https://github.com/fullstorydev/grpcurl). As an example, we can shorten 214 `/cosmos_sdk.x.bank.v1.QueryService/QueryBalance` to 215 `/cosmos.bank.Query/Balance` without losing much useful information. 216 217 RPC request and response types _should_ follow the `ServiceNameMethodNameRequest`/ 218 `ServiceNameMethodNameResponse` naming convention. i.e. for an RPC method named `Balance` 219 on the `Query` service, the request and response types would be `QueryBalanceRequest` 220 and `QueryBalanceResponse`. This will be more self-explanatory than `BalanceRequest` 221 and `BalanceResponse`. 222 223 #### Use just `Query` for the query service 224 225 Instead of [Buf's default service suffix recommendation](https://github.com/cosmos/cosmos-sdk/pull/6033), 226 we should simply use the shorter `Query` for query services. 227 228 For other types of gRPC services, we should consider sticking with Buf's 229 default recommendation. 230 231 #### Omit `Get` and `Query` from query service RPC names 232 233 `Get` and `Query` should be omitted from `Query` service names because they are 234 redundant in the fully-qualified name. For instance, `/cosmos.bank.Query/QueryBalance` 235 just says `Query` twice without any new information. 236 237 ## Future Improvements 238 239 A registry of top-level package names should be created to coordinate naming 240 across the ecosystem, prevent collisions, and also help developers discover 241 useful schemas. A simple starting point would be a git repository with 242 community-based governance. 243 244 ## Consequences 245 246 ### Positive 247 248 * names will be more concise and easier to read and type 249 * all transactions using `Any` will be at shorter (`_sdk.x` and `.v1` will be removed) 250 * `.proto` file imports will be more standard (without `"third_party/proto"` in 251 the path) 252 * code generation will be easier for clients because .proto files will be 253 in a single `proto/` directory which can be copied rather than scattered 254 throughout the Cosmos SDK 255 256 ### Negative 257 258 ### Neutral 259 260 * `.proto` files will need to be reorganized and refactored 261 * some modules may need to be marked as alpha or beta 262 263 ## References