DEP#001 Difficulty agreement protocol
- Related to: blockchain, proof-of-work
- Requires protocol upgrade: Yes
As of Duniter Protocol v1.0, the blockchain can be written only by members following this rule: at any moment, any member can issue a new block with the contents of its will.
This implies 3 problems:
Empty block easiness: an empty block is faster to compute than a full one, because the proof-of-work can be started immediately without extra computing due to the inclusion of new data (trying to include transactions, identities, certifications and check all the rules). So if a malicious node wanted to slow down the inclusion of new data in the blockchain, it would just need to compute empty blocks. Not only is this behavior annoying, but it will also have some computing advantage because of the non-inclusion of new data.
Empty blockchain: if a group of malicious nodes was to adopt the behavior described in 1), and was also big and powerful enough compared to the rest of the computing nodes, this group could easily break the currency by making empty blocks.
Deliberate forks: if a group of malicious nodes similar to 2) was trying to make blockchain forks deliberately — thanks to its high computing power, he could compute 2 valid blocks and spread each of them to half of the network, creating a fork — this could slow down the blockchain seriously.
The proposition would be to have an additional global handicap, depending on current computing members. This additional handicap would be decreased for each agreement received by other nodes and included in the computed block.
The agreements are signed by their issuer, and are issued between each proof-of-work. Only computing members can issue them. Computing members are known to be the issuers of the last
IssuersCount block in the blockchain.
In the above example, we see Node 1 (N1) has a difficulty of 60, like N2, N3, N4. This difficulty = N1's difficulty + global handicap. Let's say that here, N1's difficulty = 56 and global handicap = 4, because we have 4 computing nodes. So the basic difficulty for N1 = 60.
N1 receives 3 agreements:
- N2's agreement
6TX:B30A: translation « you can lower your difficulty by one if the block you compute contains at least 6 transactions, and is based on previous block #30 (closed), hash
- N3's agreement
4TX:B30A: translation « you can lower your difficulty by one if the block you compute contains at least 4 transactions, and is based on previous block #30 (closed), hash
- N4's agreement
4TX:B30F: translation « you can lower your difficulty by one if the block you compute contains at least 4 transactions, and is based on previous block #30 (closed), hash
If we consider N1, it's final difficulty varies depending on the block it computes:
B30A, with 6 transactions: N1's
D = 60 - 1 - 1 = 58, because he received 2 agreements from other nodes complying with this situation.
B30A, with 4 transactions: N1's
D = 60 - 1 = 59, because he received 1 agreement from other nodes complying with this situation.
B30A, with 3 transactions: N1's
D = 60, because he did not receive any agreements from other nodes complying with this situation.
B30F, with 4 transactions: N1's
D = 60 - 1 = 59
B30G, with 10 transactions: N1's
D = 60
B30G, with 20 transactions: N1's
D = 60
B30G, with 1000 transactions: N1's
D = 60
Block easiness: making empty block, whereas most of the network is expecting 4 transactions (because they see these transactions pending in their sandbox), would require the maximum difficulty, which is equal to "personal difficulty + global handicap". So the computing members will have a word on what can be and what cannot be the next block. Note how this does not prevent a malicious node to compute an empty block, but it will be harder to go against the global agreement. The more we have computing members, the harder is to go against the global will.
Empty blockchain: since it is harder to make empty blocks, it is even harder to make an empty blockchain.
Deliberate forks: even under the hypothesis of a special task force able to create blocks on their will before anyone, and make the network fork, at least this would be costly for them. It will be even more costly as they don't integrate expected data. So we have more chances that even if they create forks, at least some data is in each fork.
Global difficulty decrease: with such an algorithm, it becomes possible to encourage low nodes to compute blocks. Indeed, each node is free to share its agreement with the nodes it wants. If a node or a group of node decide to favor nodes with low computing power, they can do it. They can also not favor nodes they consider malicious.
Of course if some nodes stop sending agreements, this would globally increase the difficulty. This is very likely to happen, since all nodes are not permanent but daytime nodes.
Also, since an Agreement is issued at every block and to potentially all the computing nodes, this would make a lot of network data. We could consider a high limit for the global handicap equal to 80 (= 5*16 = 5 zeros ~= 1.048.576 times harder proof-of-work). So to have the lowest difficulty, a node would require 80 agreements: this value seems acceptable on long term run, even more as we expect thousands of transactions per block (5' block interval).
This would impact protocol's difficulty rule, block document structure, create a new « Agreement » document and handling Agreement's generation and interpretation.
The rule would be changed to include a new
Formula would change from:
MAX [ HEAD.powMin ; HEAD.powMin * FLOOR (percentRot * nbPreviousIssuers / (1 + nbBlocksSince)) ] + PERSONAL_HANDICAP
MAX [ HEAD.powMin ; HEAD.powMin * FLOOR (percentRot * nbPreviousIssuers / (1 + nbBlocksSince)) ] + PERSONAL_HANDICAP - NB_AGREEMENTS
It should be defined an Agreement document, which could look like:
Version: VERSION Type: NetworkAgreement Currency: CURRENCY NbJoiners: NB_JOINERS NbActives: NB_ACTIVES NbLeavers: NB_LEAVERS NbRevocations: NB_REVOCATIONS NbCertifications: NB_CERTS NbTransactions: NB_TX BOTTOM_SIGNATURE
It's inline format would look like:
NBJis the number of expected records under
NBAis the number of expected records under
NBLis the number of expected records under
NBRis the number of expected records under
NBCis the number of expected records under
NBTis the number of expected records under
It would be added an
NetworkAgreement list before the
NetworkAgreement: INLINE_NETWORK_AGREEMENT ...
On document's reception: parse and verify the document signature and compliance with currently generated bloc.
On block generation: generate a new block, count the number of each entity that is expected to be written, sign the document, pick a peer selection to which send the document.