Behavioral commitments
To maximize optionality in implementation, we should define the behavioral commitments over messages that make up the protocol in ways that minimize syntactic assumptions.
We have defined a set of primitive data types to be used for message definitions. This post contains a proposal on how to specify the behaviors.
Defining a behavior
A behavioral definition for a stateful entity (e.g. an agent, engine or process) should consist of the following two descriptions, conceptually separated:
- Necessary preconditions a message needs to fulfill for the behavior to be applied. This needs to be defined only in terms of the message.
- What a valid state transition implementing the behavior looks like. This can take the message and entity state as an argument and send new messages.
This distinction is induced by physics: State is local to entities, but message properties can be evaluated at any time, when a message is available.
These behavioral definitions should only concern anything externally observable, i.e. which messages are sent depending on messages received, with any internal details (e.g. optimizations, language specific representation, syntax) being left up to choice of the implementor.
Any structure that is not directly relevant to a behavior can be considered opaque
When to decompose behaviors
Behaviors will be organized in sets corresponding to certain roles in, or layers of, the protocol. To separate behaviors and increase optionality in composition, messages over which behaviors are defined should be independent from messages over which other behaviors are defined.
Generally behaviors can be (de-)composed arbitrarily. Choices about the scope of inclusion into one behavior should be made according to what level of independence of the components seems desirable. Some rules of thumb:
- Generalization should be motivated by requirements of the system, or optionality desirable from an application perspective, not an end in itself.
- If a complex behavior can be decomposed into simpler components with straightforward composition, then decomposing it might be a good choice. If the composition is harder to analyze than the initial complex object, then it schould not be decomposed.
- If the decomposition requires assumptions that can not be justified by the underlying structure, it can mislead by introducing virtual structure that can easily be collapsed by defecting parties.
Composing behaviors
Composition can happen in different ways, for example:
- Messages output by one behavior are used as inputs for another.
- Messages can contain opaque bytestrings, which handed to another behavior which performs introspection. This can happen via local calls, or the bytestring can be treated as a message to be relayed.
Remarks
- Agent interaction with a node can be modelled in the form of messages.
- Introspection through all layers of a message, or taking into account local state of all colocated components is possible in practice and can be used for optimization purposes, but it should not be required. The externally observable behavior of the entity (or composed behavior) should not differ from the case where internal separation is preserved.