# Nero: A Deterministic Leaderless Consensus Algorithm for DAG-Based Cryptocurrencies
## 3 The Nero Algorithm
### The Algorithm  
**Validation rules.** After receiving a message \(m\) of round \(r\), a correct process validates it and decides one of the following statuses:  
* Valid if there is a set of at least \(2f+1\) messages of round \(r-1\) that are compatible with the value and type of \(m\).
* Pending if there is not a set of at least \(2f+1\) messages of round \(r-1\) that are compatible with the value and type of \(m\) but it is still possible to receive new messages of round \(r-1\) to produce that set.
* Invalid if there is not a set of at least \(2f+1\) messages of round \(r-1\) that are compatible with the value and type of m, and it is not possible to receive new messages of round \(r-1\) to produce that set.  
**Decision rules.** With the start of a new round \(r+1\), a new decision has to be made to decide the message that the process is going to send in the new round. This message is based on the messages received in the previous round \(r\) (at least \(2f+1\) valid messages in total), in the following way (only one rule can be applied):  
* If process \(p\) has received at least \(2f+1\) valid messages of type COMMIT with the same value, decide that value. There is no need to send a new message because all the other correct processes will eventually receive the same messages and decide the same value as well.
* Else if process \(p\) has received at least one valid message of type COMMIT with some value \(v\), send a message of type COMMIT with value \(v\). (There cannot be two commits of different values in the same round).
* Else if process \(p\) has received at least \(2f+1\) valid messages of type VOTE with the same value, send a message of type COMMIT with that value.
* Else if process \(p\) has received at least one valid message of type COMMIT with some value \(v\), send a message of type COMMIT with that value.
* Else if process \(p\) has received at least one valid message of type COMMIT with some value \(v\) in round \(r\) and has already committed to another value \(v^{\prime}\) in round \(r^{\prime}\), send a message of type COMMIT with value \(v\) only if round \(r>r^{\prime}\). If \(r<r^{\prime}\), send a message of type COMMIT with the previous committed value \(v^{\prime}\).
* Else if process \(p\) has received at least \(f+1\) valid messages of type VOTE with value nil, send a message of type VOTE with value nil.
* If no block hash value has at least \(f+1\) votes, send a message of type VOTE with value nil.
* Else if process \(p\) has not received at least \(f+1\) valid messages of type VOTE with value nil, send a message of type VOTE with the value with most votes.  
**Execution.** In each round \(r\), a correct process waits for at least \(2f+1\) valid messages and for the timer \(t_{r}\) to expire. Every time it receives a valid message, it does the following:  
* Inserts it in the respective election state.
* Updates the tally of the election.
* Tries to validate previous pending messages based on the validation rules.
* Broadcasts \(m\) to the network.
* Computes a new message \(m^{\prime}\) of round \(r+1\) based on the received messages and the decision rules.
* Broadcasts the message \(m^{\prime}\) to the other processes.