diff --git a/documents/Specification-Format-Style-Guidelines.md b/documents/Specification-Format-Style-Guidelines.md
index 447d8186..aa58fb76 100644
--- a/documents/Specification-Format-Style-Guidelines.md
+++ b/documents/Specification-Format-Style-Guidelines.md
@@ -1,6 +1,8 @@
-# Style Guidelines for document "specification" comments
+# Protocol Buffer Style Guidelines
+
+## Style Guidelines for "specification" comments
- Wrapping is 80 characters for top-level messages.
-- Wrap everything else to 80 characters or 100 depending
+- Wrap everything else to 80 characters or 100, depending
- Prefer to wrap lines to 80 characters
- It is OK to go over 80, but less than 100, if it makes the
text clearer and easier to read.
@@ -27,10 +29,15 @@
- First line of each document block is "what is this", and should be a single
sentence. Examples: "An identifier for an account." or "A `tokenTransfer`
transaction request body.".
- - Avoid "this is a thing" type sentences, write "A thing" instead.
+ - Avoid "this is a thing" (or shorter "thing") type sentences,
+ write "A thing" instead.
- This applies for the _first sentence_ only, **not** elsewhere.
The first sentence is a "what is this" answer, not full description
and mostly just translates from "code" syntax to plain English.
+ - Minimize detail here, qualifiers, usage, etc... belong in the brief
+ description or requirements, not here.
+ - A good rule of thumb is that if this first sentence exceeds 60
+ characters, then it is trying to describe too much.
- Include a line break (`
`) after the first line, then a brief description,
if appropriate.
- Not every field needs additional description, but _every_ `message` does.
@@ -42,6 +49,9 @@
- This is a long-term goal; we have a long way to go to get to this
level of description. Every PR to change `.proto` files should seek
to improve the documentation for that file.
+ - Avoid describing what must, should, must not, or should not be
+ sent, or how the field values affect output. Those items belong in the
+ _requirements_, instead.
- After a paragraph break (a blank line for messages), one requirement per
line. Use break tags at the end of each requirement except the last.
- In field comments a `
` tag is _required_ for paragraph breaks.
@@ -74,3 +84,213 @@
Block Stream effects with a heading `### Block Stream Effects`.
- General notes go last, for `message` only, with a heading
`#### Additional Notes`.
+
+## Content Guidelines
+
+### Field Type Guidelines
+- There are some negative patterns present in existing `proto` files. These
+ SHOULD NOT be replicated in new files, when possible.
+ - Older files may use `int64` or `int32` when a `uint` is more appropriate,
+ and document a "non-negative" requirement. This SHOULD NOT be replicated.
+ in new content (files, messages, fields) we SHOULD use _unsigned_ numeric
+ types where appropriate.
+ - We MUST NOT change existing field types without very careful
+ consideration for binary compatibility and impact to clients.
+
+### Package Directive Guidelines
+- There are some negative patterns present in existing `proto` files. These
+ SHOULD NOT be replicated in new files, when possible.
+ - Older files have a `package proto;` directive. This is leftover from
+ _sample_ content, and SHOULD NOT be used in new files.
+ - To avoid major compatibility issues, particularly for SDK authors, we
+ SHOULD NOT change the `package` directive in _existing_ files.
+- For _new_ `proto` files only, the file SHOULD use a `package` directive with
+ a package that is identical to the value in the
+ `pbj.java_package` pseudo-directive.
+ - One exception to this guideline is that gRPC `service` and `rpc`
+ definitions include the package name in the url path. As a result we
+ cannot easily use full package names for these.
+ - Completely new services and gRPC endpoints SHOULD be defined alone in a
+ separate `thing_service.proto` file _without_ transaction bodies. The
+ endpoint MAY, then, be defined in a proper package.
+ - Transaction body messages and any component messages SHOULD be defined
+ in a proper package, and references in the gRPC service definition may
+ then use the full package prefix when referring to those messages.
+ - The "namespace" behavior of package names is not well supported by PBJ at
+ this time, so packages must be fully specified whenever used.
+
+
+## Examples
+
+### A Message Example
+```protobuf
+/**
+ * A transaction body to add a new consensus node to the network address book.
+ *
+ * This transaction body SHALL be considered a "privileged transaction".
+ *
+ * This message supports a transaction to create a new node in the network
+ * address book. The transaction, once complete, enables a new consensus node
+ * to join the network, and requires governing council authorization.
+ *
+ * - A `NodeCreateTransactionBody` MUST be signed by the governing council.
+ * - A `NodeCreateTransactionBody` MUST be signed by the `Key` assigned to the
+ * `admin_key` field.
+ * - The newly created node information SHALL be added to the network address
+ * book information in the network state.
+ * - The new entry SHALL be created in "state" but SHALL NOT participate in
+ * network consensus and SHALL NOT be present in network "configuration"
+ * until the next "upgrade" transaction (as noted below).
+ * - All new address book entries SHALL be added to the active network
+ * configuration during the next `freeze` transaction with the field
+ * `freeze_type` set to `PREPARE_UPGRADE`.
+ *
+ * ### Block Stream Effects
+ * Upon completion the newly assigned `node_id` SHALL be recorded in
+ * the transaction receipt.
+ * This value SHALL be the next available node identifier.
+ * Node identifiers SHALL NOT be reused.
+ */
+```
+
+### A Field Example
+```protobuf
+ /**
+ * A list of service endpoints for gossip.
+ *
+ * These endpoints SHALL represent the published endpoints to which other
+ * consensus nodes may _gossip_ transactions.
+ * These endpoints MUST specify a port.
+ * This list MUST NOT be empty.
+ * This list MUST NOT contain more than `10` entries.
+ * The first two entries in this list SHALL be the endpoints published to
+ * all consensus nodes.
+ * All other entries SHALL be reserved for future use.
+ *
+ * Each network may have additional requirements for these endpoints.
+ * A client MUST check network-specific documentation for those
+ * details.
+ * If the network configuration value `gossipFqdnRestricted` is set, then
+ * all endpoints in this list MUST supply only IP address.
+ * If the network configuration value `gossipFqdnRestricted` is _not_ set,
+ * then endpoints in this list MAY supply either IP address or FQDN, but
+ * MUST NOT supply both values for the same endpoint.
+ */
+```
+
+### An Enum Example
+```protobuf
+/**
+ * An informational enumeration of all known states.
+ * This enumeration is included here So that people know the mapping from
+ * integer to state "name".
+ *
+ * State changes are expressed in terms of changes to named states at the
+ * high level conceptual model of the state type like map key/values or
+ * queue appends. To say which state the change is on we will include an
+ * `integer` number for the state name. This is done for performance and
+ * efficiency as there will be 10s of thousands of state changes in a block.
+ *
+ * We use an integer, and provide this enumeration, for the following reasons.
+ * - If we have a extra 8-10 bytes per state change at 40-50K state changes
+ * per second then that is an extra 2.5-4 megabits of bandwidth. Compression
+ * should help a lot but that is not guaranteed.
+ * - When the state name is used as part of complex key in the big state
+ * merkle map. The smaller the key is, in bytes, the more efficient the
+ * database is, because more keys can fit in a single disk page.
+ * - When parsing keys, parsing a UTF-8 string to a Java String is a many
+ * times more expensive than parsing a VARINT to an integer.
+ *
+ * Note: This enumeration is never transmitted directly in the block stream.
+ * This enumeration is provided for clients to _interpret_ the value
+ * of the `StateChange`.`state_id` field.
+ */
+```
+
+### A Complex Message Example
+```protobuf
+/**
+ * A single Account in the Hedera distributed ledger.
+ *
+ * Each Account SHALL have a unique three-part identifier, a Key, and one
+ * or more token balances.
+ * Each Account SHALL have an alias, which has multiple forms, and MAY be set automatically.
+ * Several additional items SHALL be associated with the Account to enable
+ * full functionality.
+ * Assets SHALL be represented as linked-lists with only the "head" item
+ * referenced directly in the Account, and the remaining items SHALL be
+ * accessible via the token relation or unique tokens maps.
+ * Accounts, as most items in the network, SHALL have an expiration time,
+ * recorded as seconds since the epoch, and MUST be "renewed" for a small fee
+ * at expiration. This helps to reduce the amount of inactive accounts retained
+ * in state.
+ * Another account MAY be designated to pay any renewal fees and automatically
+ * renew an account for (by default) 30-90 days at a time as a means to
+ * optionally ensure important accounts remain active.
+ * Accounts MAY participate in securing the network by "staking" the account
+ * balances to a particular network node, and receive a portion of network
+ * fees as a reward. An account MAY optionally decline these rewards but still
+ * stake its balances.
+ * An account MAY optionally require that inbound transfer transactions be
+ * signed by that account as receiver
+ * (in addition to the sender's signature).
+ * As with all network entities, Account ID SHALL be represented as
+ * shard.realm.X.
+ * Alias and contractId SHALL be additional identifiers used to connect accounts
+ * to transactions before the account is fully enabled,
+ * or in EVM contracts.
+ *
+ * ---
+ *
+ * #### Alias
+ * There is considerable complexity with `alias` (aka `evm_address`) for
+ * Accounts. Much of this comes from the existence of a "hidden" alias for
+ * almost all accounts, and the reuse of the alias field for both EVM reference
+ * and "automatic" account creation.
+ *
+ * For the purposes of this specification, we will use the following terms for
+ * clarity.
+ * - `key_alias` is the account public key as a protobuf serialized message
+ * and used for auto-creation and subsequent lookup. This is only valid if
+ * the account key is a
+ * single `primitive` key, either ED25519 or ECDSA_SECP256K1.
+ * - `evm_address` exists for every account and is one of
+ * - `contract_address`, which is the 20 byte EVM contract address per
+ * EIP-1014
+ * - `evm_key_address`, which is the keccak-256 hash of a ECDSA_SECP256K1
+ * `primitive` key.
+ * - This is for accounts lazy-created from EVM public keys, when the
+ * corresponding ECDSA_SECP256K1 public key is presented in a
+ * transaction signed by the private key for that public key, the
+ * account is created that key assigned, and the protobuf-serialized
+ * form is set as the account alias.
+ * - `long_zero`, is a synthetic 20 byte address inferred for "normally"
+ * created accounts. It is constructed from the "standard" AccountID as
+ * follows.
+ * - 4 byte big-endian shard number
+ * - 8 byte big-endian realm number
+ * - 8 byte big-endian entity number
+ *
+ * The `alias` field in the `Account` message SHALL contain one of four values
+ * for any given account.
+ * - The `key_alias`, if the account was created by transferring HBAR to the
+ * account referenced by `key_alias`.
+ * - The `evm_key_address` if the account was created from an EVM public key
+ * - The `contract_address` if the account belongs to an EVM contract
+ * - Not-Set/null/Bytes.EMPTY (collectively `null`) if the account was
+ * created normally
+ *
+ * If the `alias` field of an `Account` is any form of `null`, then the account
+ * MAY be referenced by `alias` in an `AccountID` by using the `long_zero`
+ * address for the account. This "hidden default" alias SHALL NOT be stored,
+ * but is synthesized by the node software as needed, and may be synthesized by
+ * an EVM contract or client software as well.
+ *
+ * An AccountID in a transaction MAY reference an `Account` with
+ * `shard`.`realm`.`alias`.
+ * If the account `alias` field is set for an Account, that value SHALL be the
+ * account alias.
+ * If the account `alias` field is not set for an Account, the `long_zero`
+ * alias SHALL be the account alias.
+ */
+```
diff --git a/services/state/token/account.proto b/services/state/token/account.proto
index 6223c34b..301ecac8 100644
--- a/services/state/token/account.proto
+++ b/services/state/token/account.proto
@@ -43,37 +43,33 @@ option java_multiple_files = true;
/**
* A single Account in the Hedera distributed ledger.
*
- * Each Account has a unique three-part identifier, a Key, and one or more token
- * balances.
- *
- * Accounts also have an alias, which has multiple forms, and may be set
- * automatically.
- *
- * Several additional items are associated with the Account to enable full
- * functionality.
- *
- * Assets are represented as linked-lists with only the "head" item referenced
- * directly in the Account, and the remaining items are accessible via the
- * token relation or unique tokens maps.
- *
- * Accounts, as most items in the network, have an expiration time, recorded as
- * seconds since the epoch, and must be "renewed" for a small fee at expiration.
- * This helps to reduce the amount of inactive accounts retained in state.
- * Another account may be designated to pay any renewal fees and automatically
- * renew the account for (by default) 30-90 days at a time as a means to
- * optionally ensure important accounts remain active.
- *
- * Accounts may participate in securing the network by "staking" the account
- * balances to a particular network node, and receive a portion of network fees
- * as a reward. An account may optionally decline these rewards but still stake
- * its balances.
- *
- * An account may optionally require that inbound transfer transactions be
- * signed by that account as receiver (in addition to the sender's signature).
- *
- * As with all network entities, Account ID is represented as shard.realm.X.
- * Alias and contractId are additional identifiers used to connect accounts to
- * transactions before the account is fully enabled, or in EVM contracts.
+ * Each Account SHALL have a unique three-part identifier, a Key, and one
+ * or more token balances.
+ * Each Account SHALL have an alias, which has multiple forms, and MAY be set automatically.
+ * Several additional items SHALL be associated with the Account to enable
+ * full functionality.
+ * Assets SHALL be represented as linked-lists with only the "head" item
+ * referenced directly in the Account, and the remaining items SHALL be
+ * accessible via the token relation or unique tokens maps.
+ * Accounts, as most items in the network, SHALL have an expiration time,
+ * recorded as seconds since the epoch, and MUST be "renewed" for a small fee
+ * at expiration. This helps to reduce the amount of inactive accounts retained
+ * in state.
+ * Another account MAY be designated to pay any renewal fees and automatically
+ * renew an account for (by default) 30-90 days at a time as a means to
+ * optionally ensure important accounts remain active.
+ * Accounts MAY participate in securing the network by "staking" the account
+ * balances to a particular network node, and receive a portion of network
+ * fees as a reward. An account MAY optionally decline these rewards but still
+ * stake its balances.
+ * An account MAY optionally require that inbound transfer transactions be
+ * signed by that account as receiver
+ * (in addition to the sender's signature).
+ * As with all network entities, Account ID SHALL be represented as
+ * shard.realm.X.
+ * Alias and contractId SHALL be additional identifiers used to connect accounts
+ * to transactions before the account is fully enabled,
+ * or in EVM contracts.
*
* ---
*