6.1 Objects of Consensus
6.1.1 Preliminaries
6.1.1.1 Motivation
FPC is a binary voting protocol where each node starts with an initial opinion (a nulled boolean) on an object. Nodes then exchange queries and responses about their opinions during several rounds, until each node terminates with a final boolean value: see specification .
FPC votes on two specific objects types: messages, in order to enforce timestamps, and transactions, in order to decide double spends. Additionally, applications can use FPC to query opinions about their opinion on other object types, although there is no guarantee that they will get a response.
The FPC is agnostic about the rest of the protocol, particularly the questions being decided voting and how the initial opinions are set. We require a generic way for FPC to interact with data structures in other applications. Specifically, an application needs a way to trigger FPC run.
Deciding when FPC should run is a delicate question for two reasons.
- It is inefficient for FPC to vote on every single transaction.
- If only a sub set of nodes participate in FPC, they are more vulnerable to attack since the consensus mana held by this collection of nodes is potentially much smaller. Thus, since it cannot vote on everything, it must use subjective criterion to trigger voting which does not leave any group vulnerable to attack.
Voting is a two-part process: querying and answering queries. The function QueryStatus
determines if a node should query about a particular object, and the function AnswerStatus
determines if the node should respond.
6.1.1.2 Summary
This specification describes how this binary voting protocol interacts with the rest of the IOTA protocol. Specifically, we define two functions, QueryStatus
and AnswerStatus
which govern when an object should be included in a query or response respectively. These functions depend on the metatdata opinionField
which is also defined in this specification.
This specification only includes the format on how applications requiring FPC should interact with it, not how to set initial opinions or, more specifically, opinionField
. For this information, see .
6.1.1.3 Dependencies
This specification depends on the following specifications
- FPC
- Opinion Setting
6.1.1.4 Parameters and Lists
Name | Type | Description |
---|---|---|
DSMALL | duration | small estimated network delay, set to 5 seconds |
votingEnabledObjectTypes | list | object types which will be voted upon |
6.1.2 Detailed Design
6.1.2.1 Voting Objects List
FPC can potentially vote on a variety of matters. The votingEnabledObjectTypes
effectively lists which things will be voted upon by listing the object types which must be queried by FPC. Specifically, when FPC prepares a query, it iterates through each object type, and then finds which objects of that type it must include in the query.
By default, the object types message
and transaction
are in the list votingEnabledObjectTypes
. However, a second layer application can add other object types to this list, allowing other applications to use FPC. These applications will have no guarantee that they will receive responses with about custom object types, particularly if the application is not widely used.
6.1.2.2 How Opinions on Objects Are Stored
For every object whose type is in votingEnabledObjectTypes
, that the local meta data stored with the object must include an opinionField
which is either NULL
or the triplet (opinion,level,timeFormed)
. The field opinion
is a nullable boolean value, level
is a number in the list , and timeFormed
is the time the field was changed from NULL
.
As will be discussed in a different specification, an opinion field will be NULL
until the node has received information allowing it to form an opinion, e.g. detect a conflict. For example, a transaction should have opinion field NULL
until a conflict is detected. Such transactions should be considered "good", and, in the honest setting, most transactions will have a NULL
opinion.
6.1.2.3 Query Status
When FPC prepares a query , see the FPC specification, it shall determine which objects to include. Conceptually, for each type in votingEnabledObjectTypes
, the node shall iterate through all objects of that type and individually decide if that object is to be included in the query. Clearly, this iteration would be inefficient expensive, and a node can use some method to speed up the process. However, this is an implementation detail and thus beyond the scope of this document.
To determine whether or not each object should be included into a query, a node shall apply the following QueryStatus
function. If the function returns true, then the object should be included into the query.
FUNCTION Bool = QueryStatus(type,objectID)
IF type not in VotingEnabledObjectTypes
RETURN FALSE
ELSE IF opinionField != NULL AND level =1 and currentTime > timeFormed+DSMALL
RETURN TRUE
ELSE RETURN FALSE
IF the object does not exist
RETURN `FALSE`.
When FPC succesfully stops voting on an object, it sets in the opinionField
the opinion
to the final opinion and modifies level
to 2
so that QueryStatus
returns false.
6.1.2.4 Answer Status
Every time FPC receives a query request, it checks whether or not it should reply; see FPC. To do so, it applies the following AnswerStatus
function to object in the query request to determine if a response should be made. If AnswerStatus
returns FALSE
for any object in the query request, a query response will not be prepared.
FUNCTION Bool=AnswerStatus(type,objectID)
If type not in VotingEnabledObjectTypes
RETURN FALSE
ELSE IF opinionField not = NULL AND (level = 1 OR level = 2)
RETURN TRUE
ELSE RETURN FALSE
Lastly, if the object does not exist, the function should return FALSE
.
6.1.3 Rationale and Alternatives
The level
field indicates the level of knowledge. It tells us information about what other nodes know.
- Level 1 means that the node only knows that it holds this opinion.
- Level 2 means that the node knows that all nodes have this opinion too (with high probability).
- Level 3 means that the node knows that all nodes have level 2 knowledge (with high probability).
If a node node only has level 1 knowledge, it needs to vote. However, if it has level 2 knowledge, it does not need to query as it knows that all nodes have the same opinion. With level 3 knowledge, it knows that no other nodes have level 2 knowledge and thus should not send its node queries. Thus, with level 3 knowledge, the node does not need to respond. The level of knowledge is the primary criterion in these functions.
Moreover, we should not query about objects whose opinion is NULL
. In a similar vein, we need should not query about an object until d
time after the opinion was set, so we can be sure that all other nodes have set their opinion too.
Alternatively, we can attempt to manage the same system with a series of finality flags. However, this has two problems. First, we either mark objects which we have never voted upon as final, or some objects will never get a finality flag. This leads to some complicated, unintuitive logic. Second, if an attacker can cause only small portions of the network to vote on an object, that vote would be susceptible to an attack. Thus we need consensus about what to vote on. However, if voting is a binary "yes" or "no", we would need a consensus algorithm to determine when to vote. The levels of knowledge does not treat voting in a binary way, bypassing this problem.