.. contents:: Table of Contents :depth: 3 .. _ref_schema.proto: schema.proto ================================================================== This file defines the protocol between relays and clients. It is orthogonal to the store registry and other smart contracts. Messages must be prefixed with their acompanying encoding number as a single byte. encoding.txt defines the number for each message. Furthermore, we expect only one message per write/binary frame. This means no buffering of multiple messages into a single write. The protocol offers repeated fields where approriate for higher throughput. A suggested transport is WebSocket over HTTPS but the protocol is agnostic, as long as it can handle binary data and keeps the framing intact. For upgrades there exists a VERSION file in the root of the repository. The VERSION is a single unsigned integer, incremented for each change. The client and relay must agree on the VERSION before starting the protocol. In the case of WebSocket, the VERSION can be compared via the URL. The relay must close the connection if the VERSION isn't supported. As of this version, the protocol is grouped into 2 categories: Events, which define the content of a Store, and Request/Response methods to exchange information. .. index:: StoreManifest .. _ref_market.mass.StoreManifest: StoreManifest ------------------------------------------------------------------ First genisis message of a store. Has to be the first message that is written and can only be written once. Use UpdateManifest to make changes. .. csv-table:: StoreManifest type fields :header: "Field", "Type", "Label", "Description" :widths: auto "event_id", ":ref:`ref_bytes`", "", "The event_id is a unique identifier for an event. Currently it's 32 bytes of random data. It also functions as a nonce for The events signature. The global identifier of an Item should also include the store_token_id. hash(store_token_id:signature) might suffice then with a smaller nonce." "store_token_id", ":ref:`ref_bytes`", "", "The NFT Token ID used in StoreReg.registerStore(). Checkout will ownerOf() this to determine the addr for PurchaseFactory." "domain", ":ref:`ref_string`", "", "Website URL of the store TODO: might change this to metdata inside the NFT URL." "published_tag_id", ":ref:`ref_bytes`", "", "the system tag used to list active items" .. index:: UpdateManifest .. _ref_market.mass.UpdateManifest: UpdateManifest ------------------------------------------------------------------ Used to update the store manifest. The Field enum determines the field to be updated and the value to be used. .. csv-table:: UpdateManifest type fields :header: "Field", "Type", "Label", "Description" :widths: auto "event_id", ":ref:`ref_bytes`", "", "See StoreManifest for details" "field", ":ref:`ref_market.mass.UpdateManifest.ManifestField`", "", "Defines the field to be updated and determines the value to be used." "string", ":ref:`ref_string`", "value", "" "tag_id", ":ref:`ref_bytes`", "value", "See event_id for details" "erc20_addr", ":ref:`ref_bytes`", "value", "20 bytes" .. index:: CreateItem .. _ref_market.mass.CreateItem: CreateItem ------------------------------------------------------------------ Creates an item in the store. .. csv-table:: CreateItem type fields :header: "Field", "Type", "Label", "Description" :widths: auto "event_id", ":ref:`ref_bytes`", "", "See StoreManifest for details" "price", ":ref:`ref_string`", "", "decimal number as a string. numbers need to be always formatted to 2 decimal places. the demcimal place must use a dot ('.') as the separator." "metadata", ":ref:`ref_bytes`", "", "should be valid JSON TODO: make a json schmea with minimal/required fields" .. index:: UpdateItem .. _ref_market.mass.UpdateItem: UpdateItem ------------------------------------------------------------------ UpdateItem changes the price or metadata of an item. Follows the same pattern as UpdateManifest. .. csv-table:: UpdateItem type fields :header: "Field", "Type", "Label", "Description" :widths: auto "event_id", ":ref:`ref_bytes`", "", "See StoreManifest for details" "item_id", ":ref:`ref_bytes`", "", "the event_id of the CreateItem event" "field", ":ref:`ref_market.mass.UpdateItem.ItemField`", "", "" "price", ":ref:`ref_string`", "value", "decimal number. See CreateItem for formatting." "metadata", ":ref:`ref_bytes`", "value", "" .. index:: CreateTag .. _ref_market.mass.CreateTag: CreateTag ------------------------------------------------------------------ Creates a tag in the store. These can be used to group items into categories. There are also a couple of system-level tags, like published. Thse are used to filter items in the store. .. csv-table:: CreateTag type fields :header: "Field", "Type", "Label", "Description" :widths: auto "event_id", ":ref:`ref_bytes`", "", "See StoreManifest for details" "name", ":ref:`ref_string`", "", "" .. index:: AddToTag .. _ref_market.mass.AddToTag: AddToTag ------------------------------------------------------------------ Adds an item to a tag. TODO: might change this to the Update* pattern. .. csv-table:: AddToTag type fields :header: "Field", "Type", "Label", "Description" :widths: auto "event_id", ":ref:`ref_bytes`", "", "See StoreManifest for details" "tag_id", ":ref:`ref_bytes`", "", "" "item_id", ":ref:`ref_bytes`", "", "" .. index:: RemoveFromTag .. _ref_market.mass.RemoveFromTag: RemoveFromTag ------------------------------------------------------------------ Removes an item from a tag. TODO: might change this to the Update* pattern. .. csv-table:: RemoveFromTag type fields :header: "Field", "Type", "Label", "Description" :widths: auto "event_id", ":ref:`ref_bytes`", "", "See StoreManifest for details" "tag_id", ":ref:`ref_bytes`", "", "" "item_id", ":ref:`ref_bytes`", "", "" .. index:: RenameTag .. _ref_market.mass.RenameTag: RenameTag ------------------------------------------------------------------ Renames a tag. TODO: might change this to the Update* pattern. .. csv-table:: RenameTag type fields :header: "Field", "Type", "Label", "Description" :widths: auto "event_id", ":ref:`ref_bytes`", "", "See StoreManifest for details" "tag_id", ":ref:`ref_bytes`", "", "" "name", ":ref:`ref_string`", "", "" .. index:: DeleteTag .. _ref_market.mass.DeleteTag: DeleteTag ------------------------------------------------------------------ Deletes a tag. TODO: might change this to the Update* pattern. .. csv-table:: DeleteTag type fields :header: "Field", "Type", "Label", "Description" :widths: auto "event_id", ":ref:`ref_bytes`", "", "See StoreManifest for details" "tag_id", ":ref:`ref_bytes`", "", "" .. index:: ChangeStock .. _ref_market.mass.ChangeStock: ChangeStock ------------------------------------------------------------------ ChangeStock is used to update the stock of on or more items. Created by the relay after a cart has been paied for. .. csv-table:: ChangeStock type fields :header: "Field", "Type", "Label", "Description" :widths: auto "event_id", ":ref:`ref_bytes`", "", "See StoreManifest for details" "item_ids", ":ref:`ref_bytes`", "repeated", "length needs to match the length of the diff field" "diffs", ":ref:`ref_sint32`", "repeated", "" "cart_id", ":ref:`ref_bytes`", "", "(optional) only set by the relay. signals payment completion after a CommitCartRequest" "tx_hash", ":ref:`ref_bytes`", "", "" .. index:: NewKeyCard .. _ref_market.mass.NewKeyCard: NewKeyCard ------------------------------------------------------------------ created by the relay when a user enrolls a key card .. csv-table:: NewKeyCard type fields :header: "Field", "Type", "Label", "Description" :widths: auto "event_id", ":ref:`ref_bytes`", "", "See StoreManifest for details" "user_wallet_addr", ":ref:`ref_bytes`", "", "" "card_public_key", ":ref:`ref_bytes`", "", "" .. index:: CreateCart .. _ref_market.mass.CreateCart: CreateCart ------------------------------------------------------------------ CreateCart is used to create a new cart. .. csv-table:: CreateCart type fields :header: "Field", "Type", "Label", "Description" :widths: auto "event_id", ":ref:`ref_bytes`", "", "See StoreManifest for details" .. index:: ChangeCart .. _ref_market.mass.ChangeCart: ChangeCart ------------------------------------------------------------------ ChangeCart is used to add or remove items from a cart. .. csv-table:: ChangeCart type fields :header: "Field", "Type", "Label", "Description" :widths: auto "event_id", ":ref:`ref_bytes`", "", "See StoreManifest for details" "cart_id", ":ref:`ref_bytes`", "", "" "item_id", ":ref:`ref_bytes`", "", "" "quantity", ":ref:`ref_sint32`", "", "" .. index:: CartFinalized .. _ref_market.mass.CartFinalized: CartFinalized ------------------------------------------------------------------ Created by the relay after a CommitCartRequest. It signals that a cart is about to be payed and can not be changed anymore. .. csv-table:: CartFinalized type fields :header: "Field", "Type", "Label", "Description" :widths: auto "event_id", ":ref:`ref_bytes`", "", "See StoreManifest for details" "cart_id", ":ref:`ref_bytes`", "", "" "purchase_addr", ":ref:`ref_bytes`", "", "the address the user needs to send the funds to" "erc20_addr", ":ref:`ref_bytes`", "", "(optional) copied from CommitCartRequest" "sub_total", ":ref:`ref_string`", "", "" "sales_tax", ":ref:`ref_string`", "", "" "total", ":ref:`ref_string`", "", "= subtotal + sales_tax" "total_in_crypto", ":ref:`ref_string`", "", "The exact amount to transfer to the purchase_address. bigint as string." .. index:: CartAbandoned .. _ref_market.mass.CartAbandoned: CartAbandoned ------------------------------------------------------------------ Either created by a relay for a carts that haven't been payed in time. Or by a clerk, for eg. when the customer steps back from the purchase. This frees up the items locked up in the finalized cart. .. csv-table:: CartAbandoned type fields :header: "Field", "Type", "Label", "Description" :widths: auto "event_id", ":ref:`ref_bytes`", "", "See StoreManifest for details" "cart_id", ":ref:`ref_bytes`", "", "" .. index:: Event .. _ref_market.mass.Event: Event ------------------------------------------------------------------ Event is the transport wrapper for a single Event. For signatures we use https://eips.ethereum.org/EIPS/eip-712. The structured data definition are specified in `typedData.json`. The KeyCard keypair is used to sign or verify the data. The Set of all valid keys is all NewKeyCard events plus the Relays assigned on the StoreReg smart contract. Special care must be taken for Events with optional and union fields. Specifically these are `UpdateManifest`, `UpdateItem` and `ChangeStock`. Some implementations of `eth_signTypedData` are fine with `null` fields, while others aren't. Therefore, the structured data specification needs to be pruned from fields that are not set. .. csv-table:: Event type fields :header: "Field", "Type", "Label", "Description" :widths: auto "signature", ":ref:`ref_bytes`", "", "" "store_manifest", ":ref:`ref_market.mass.StoreManifest`", "union", "" "update_manifest", ":ref:`ref_market.mass.UpdateManifest`", "union", "" "create_item", ":ref:`ref_market.mass.CreateItem`", "union", "" "update_item", ":ref:`ref_market.mass.UpdateItem`", "union", "" "create_tag", ":ref:`ref_market.mass.CreateTag`", "union", "" "add_to_tag", ":ref:`ref_market.mass.AddToTag`", "union", "" "remove_from_tag", ":ref:`ref_market.mass.RemoveFromTag`", "union", "" "rename_tag", ":ref:`ref_market.mass.RenameTag`", "union", "" "delete_tag", ":ref:`ref_market.mass.DeleteTag`", "union", "" "create_cart", ":ref:`ref_market.mass.CreateCart`", "union", "" "change_cart", ":ref:`ref_market.mass.ChangeCart`", "union", "" "cart_finalized", ":ref:`ref_market.mass.CartFinalized`", "union", "" "cart_abandoned", ":ref:`ref_market.mass.CartAbandoned`", "union", "" "change_stock", ":ref:`ref_market.mass.ChangeStock`", "union", "" "new_key_card", ":ref:`ref_market.mass.NewKeyCard`", "union", "" .. index:: AuthenticateRequest .. _ref_market.mass.AuthenticateRequest: AuthenticateRequest ------------------------------------------------------------------ Initiates the challenge/response protocol. .. csv-table:: AuthenticateRequest type fields :header: "Field", "Type", "Label", "Description" :widths: auto "request_id", ":ref:`ref_bytes`", "", "See PingRequest for details" "public_key", ":ref:`ref_bytes`", "", "of their keyCard" .. index:: AuthenticateResponse .. _ref_market.mass.AuthenticateResponse: AuthenticateResponse ------------------------------------------------------------------ Returns an error if the public key is not an enrolled KeyCard. or a challenge to be signed by the KeyCard. .. csv-table:: AuthenticateResponse type fields :header: "Field", "Type", "Label", "Description" :widths: auto "request_id", ":ref:`ref_bytes`", "", "" "error", ":ref:`ref_market.mass.Error`", "", "" "challenge", ":ref:`ref_bytes`", "", "" .. index:: ChallengeSolvedRequest .. _ref_market.mass.ChallengeSolvedRequest: ChallengeSolvedRequest ------------------------------------------------------------------ Completes authentication by supplying the signature over the challenge. .. csv-table:: ChallengeSolvedRequest type fields :header: "Field", "Type", "Label", "Description" :widths: auto "request_id", ":ref:`ref_bytes`", "", "" "signature", ":ref:`ref_bytes`", "", "" .. index:: ChallengeSolvedResponse .. _ref_market.mass.ChallengeSolvedResponse: ChallengeSolvedResponse ------------------------------------------------------------------ No error means the user is authenticated. .. csv-table:: ChallengeSolvedResponse type fields :header: "Field", "Type", "Label", "Description" :widths: auto "request_id", ":ref:`ref_bytes`", "", "" "error", ":ref:`ref_market.mass.Error`", "", "" .. index:: CommitCartRequest .. _ref_market.mass.CommitCartRequest: CommitCartRequest ------------------------------------------------------------------ Initiate check out of a cart .. csv-table:: CommitCartRequest type fields :header: "Field", "Type", "Label", "Description" :widths: auto "request_id", ":ref:`ref_bytes`", "", "" "cart_id", ":ref:`ref_bytes`", "", "" "erc20_addr", ":ref:`ref_bytes`", "", "emtpy/unset means vanilla ETH" .. index:: CommitCartResponse .. _ref_market.mass.CommitCartResponse: CommitCartResponse ------------------------------------------------------------------ Returns an error if the cart is already finalized. No error blocks further changes to a cart and starts the payment process. TODO: we might change the payload in this to an Event for longevity. .. csv-table:: CommitCartResponse type fields :header: "Field", "Type", "Label", "Description" :widths: auto "request_id", ":ref:`ref_bytes`", "", "" "error", ":ref:`ref_market.mass.Error`", "", "" "cart_finalized_id", ":ref:`ref_bytes`", "", "" .. index:: GetBlobUploadURLRequest .. _ref_market.mass.GetBlobUploadURLRequest: GetBlobUploadURLRequest ------------------------------------------------------------------ Get an URL to upload a blob to. This exists for future-proofing the protocol and reduce stress on the websocket connection. .. csv-table:: GetBlobUploadURLRequest type fields :header: "Field", "Type", "Label", "Description" :widths: auto "request_id", ":ref:`ref_bytes`", "", "" .. index:: GetBlobUploadURLResponse .. _ref_market.mass.GetBlobUploadURLResponse: GetBlobUploadURLResponse ------------------------------------------------------------------ Returns a single-use URL to upload a blob to. The HTTP response will contain the blob's IPFS path. .. csv-table:: GetBlobUploadURLResponse type fields :header: "Field", "Type", "Label", "Description" :widths: auto "request_id", ":ref:`ref_bytes`", "", "" "error", ":ref:`ref_market.mass.Error`", "", "" "url", ":ref:`ref_string`", "", "" .. index:: EventWriteRequest .. _ref_market.mass.EventWriteRequest: EventWriteRequest ------------------------------------------------------------------ Used by the Client to write a single event to the store. .. csv-table:: EventWriteRequest type fields :header: "Field", "Type", "Label", "Description" :widths: auto "request_id", ":ref:`ref_bytes`", "", "" "event", ":ref:`ref_market.mass.Event`", "", "" .. index:: EventWriteResponse .. _ref_market.mass.EventWriteResponse: EventWriteResponse ------------------------------------------------------------------ Might return an error if the event or its signature is invalid. If no error is returned, the new_store_hash is the hash of the store with the new event applied. The event_sequence_no is the index of the event in the stores log. .. csv-table:: EventWriteResponse type fields :header: "Field", "Type", "Label", "Description" :widths: auto "request_id", ":ref:`ref_bytes`", "", "" "error", ":ref:`ref_market.mass.Error`", "", "" "new_store_hash", ":ref:`ref_bytes`", "", "" "event_sequence_no", ":ref:`ref_uint64`", "", "" .. index:: SyncStatusRequest .. _ref_market.mass.SyncStatusRequest: SyncStatusRequest ------------------------------------------------------------------ Sent by the relay to signal the number of unpushed events. .. csv-table:: SyncStatusRequest type fields :header: "Field", "Type", "Label", "Description" :widths: auto "request_id", ":ref:`ref_bytes`", "", "" "unpushed_events", ":ref:`ref_uint64`", "", "" .. index:: SyncStatusResponse .. _ref_market.mass.SyncStatusResponse: SyncStatusResponse ------------------------------------------------------------------ .. csv-table:: SyncStatusResponse type fields :header: "Field", "Type", "Label", "Description" :widths: auto "request_id", ":ref:`ref_bytes`", "", "" "error", ":ref:`ref_market.mass.Error`", "", "" .. index:: EventPushRequest .. _ref_market.mass.EventPushRequest: EventPushRequest ------------------------------------------------------------------ Used by the relay to push events to the client. Will not sent more events until the client has acknowledged the last batch. .. csv-table:: EventPushRequest type fields :header: "Field", "Type", "Label", "Description" :widths: auto "request_id", ":ref:`ref_bytes`", "", "" "events", ":ref:`ref_market.mass.Event`", "repeated", "" .. index:: EventPushResponse .. _ref_market.mass.EventPushResponse: EventPushResponse ------------------------------------------------------------------ .. csv-table:: EventPushResponse type fields :header: "Field", "Type", "Label", "Description" :widths: auto "request_id", ":ref:`ref_bytes`", "", "" "error", ":ref:`ref_market.mass.Error`", "", "" .. index:: PingRequest .. _ref_market.mass.PingRequest: PingRequest ------------------------------------------------------------------ Sent by the relay to check for the clients liveness. The client needs to respond with a PingResponse. The relay will close the connection if the client doesn't respond 3 times. .. csv-table:: PingRequest type fields :header: "Field", "Type", "Label", "Description" :widths: auto "request_id", ":ref:`ref_bytes`", "", "16 bytes, chosen by the sender but should be random. Used to match the response to the request." .. index:: PingResponse .. _ref_market.mass.PingResponse: PingResponse ------------------------------------------------------------------ .. csv-table:: PingResponse type fields :header: "Field", "Type", "Label", "Description" :widths: auto "request_id", ":ref:`ref_bytes`", "", "" "error", ":ref:`ref_market.mass.Error`", "", "" .. index:: Error .. _ref_market.mass.Error: Error ------------------------------------------------------------------ .. csv-table:: Error type fields :header: "Field", "Type", "Label", "Description" :widths: auto "code", ":ref:`ref_string`", "", "TODO: make a list of error codes, maybe enum" "message", ":ref:`ref_string`", "", "" .. _ref_market.mass.UpdateItem.ItemField: UpdateItem.ItemField ------------------------------------------------------------------ .. csv-table:: Enum UpdateItem.ItemField values :header: "Name", "Number", "Description" :widths: auto "ITEM_FIELD_UNSPECIFIED", "0", "" "ITEM_FIELD_PRICE", "1", "" "ITEM_FIELD_METADATA", "2", "" .. _ref_market.mass.UpdateManifest.ManifestField: UpdateManifest.ManifestField ------------------------------------------------------------------ for now we assume the owner can't be changed .. csv-table:: Enum UpdateManifest.ManifestField values :header: "Name", "Number", "Description" :widths: auto "MANIFEST_FIELD_UNSPECIFIED", "0", "needed as a side-effect of what protobuf calls "open enums"" "MANIFEST_FIELD_DOMAIN", "1", "uses value:3 (type string)" "MANIFEST_FIELD_PUBLISHED_TAG", "2", "uses value:4 (type event_id)" "MANIFEST_FIELD_ADD_ERC20", "3", "add uses value:5 (addrress)" "MANIFEST_FIELD_REMOVE_ERC20", "4", "uses value:5 (address)" .. _ref_scala_types: Scalar Value Types ~~~~~~~~~~~~~~~~~~ .. _ref_double: double ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. csv-table:: double language representation :header: ".proto Type", "C++", "Java", "Python", "Go", "C#", "PHP", "Ruby" :widths: auto "double", "double", "double", "float", "float64", "double", "float", "Float" .. _ref_float: float ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. csv-table:: float language representation :header: ".proto Type", "C++", "Java", "Python", "Go", "C#", "PHP", "Ruby" :widths: auto "float", "float", "float", "float", "float32", "float", "float", "Float" .. _ref_int32: int32 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. .. csv-table:: int32 language representation :header: ".proto Type", "C++", "Java", "Python", "Go", "C#", "PHP", "Ruby" :widths: auto "int32", "int32", "int", "int", "int32", "int", "integer", "Bignum or Fixnum (as required)" .. _ref_int64: int64 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. .. csv-table:: int64 language representation :header: ".proto Type", "C++", "Java", "Python", "Go", "C#", "PHP", "Ruby" :widths: auto "int64", "int64", "long", "int/long", "int64", "long", "integer/string", "Bignum" .. _ref_uint32: uint32 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Uses variable-length encoding. .. csv-table:: uint32 language representation :header: ".proto Type", "C++", "Java", "Python", "Go", "C#", "PHP", "Ruby" :widths: auto "uint32", "uint32", "int", "int/long", "uint32", "uint", "integer", "Bignum or Fixnum (as required)" .. _ref_uint64: uint64 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Uses variable-length encoding. .. csv-table:: uint64 language representation :header: ".proto Type", "C++", "Java", "Python", "Go", "C#", "PHP", "Ruby" :widths: auto "uint64", "uint64", "long", "int/long", "uint64", "ulong", "integer/string", "Bignum or Fixnum (as required)" .. _ref_sint32: sint32 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. .. csv-table:: sint32 language representation :header: ".proto Type", "C++", "Java", "Python", "Go", "C#", "PHP", "Ruby" :widths: auto "sint32", "int32", "int", "int", "int32", "int", "integer", "Bignum or Fixnum (as required)" .. _ref_sint64: sint64 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. .. csv-table:: sint64 language representation :header: ".proto Type", "C++", "Java", "Python", "Go", "C#", "PHP", "Ruby" :widths: auto "sint64", "int64", "long", "int/long", "int64", "long", "integer/string", "Bignum" .. _ref_fixed32: fixed32 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Always four bytes. More efficient than uint32 if values are often greater than 2^28. .. csv-table:: fixed32 language representation :header: ".proto Type", "C++", "Java", "Python", "Go", "C#", "PHP", "Ruby" :widths: auto "fixed32", "uint32", "int", "int", "uint32", "uint", "integer", "Bignum or Fixnum (as required)" .. _ref_fixed64: fixed64 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Always eight bytes. More efficient than uint64 if values are often greater than 2^56. .. csv-table:: fixed64 language representation :header: ".proto Type", "C++", "Java", "Python", "Go", "C#", "PHP", "Ruby" :widths: auto "fixed64", "uint64", "long", "int/long", "uint64", "ulong", "integer/string", "Bignum" .. _ref_sfixed32: sfixed32 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Always four bytes. .. csv-table:: sfixed32 language representation :header: ".proto Type", "C++", "Java", "Python", "Go", "C#", "PHP", "Ruby" :widths: auto "sfixed32", "int32", "int", "int", "int32", "int", "integer", "Bignum or Fixnum (as required)" .. _ref_sfixed64: sfixed64 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Always eight bytes. .. csv-table:: sfixed64 language representation :header: ".proto Type", "C++", "Java", "Python", "Go", "C#", "PHP", "Ruby" :widths: auto "sfixed64", "int64", "long", "int/long", "int64", "long", "integer/string", "Bignum" .. _ref_bool: bool ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. csv-table:: bool language representation :header: ".proto Type", "C++", "Java", "Python", "Go", "C#", "PHP", "Ruby" :widths: auto "bool", "bool", "boolean", "boolean", "bool", "bool", "boolean", "TrueClass/FalseClass" .. _ref_string: string ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A string must always contain UTF-8 encoded or 7-bit ASCII text. .. csv-table:: string language representation :header: ".proto Type", "C++", "Java", "Python", "Go", "C#", "PHP", "Ruby" :widths: auto "string", "string", "String", "str/unicode", "string", "string", "string", "String (UTF-8)" .. _ref_bytes: bytes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ May contain any arbitrary sequence of bytes. .. csv-table:: bytes language representation :header: ".proto Type", "C++", "Java", "Python", "Go", "C#", "PHP", "Ruby" :widths: auto "bytes", "string", "ByteString", "str", "[]byte", "ByteString", "string", "String (ASCII-8BIT)"