QIP: 8
Layer: Consensus (hard fork)
Title: Dynamic Tree Expansion
Author: wizeguyy <[email protected]>
Comments-Summary: No comments yet.
Comments-URI: https://github.com/quainetwork/qips/wiki/Comments:QIP-0008
Status: Draft
Type: Standards Track
Created: 2024-01-26
License: BSD-2-Clause
This QIP defines an algorithm by which different chains within the Quai tree of chains may agree to expand the tree and activate new chains. This algorithm provides a deterministic decision based on hash measurements in each section of the tree.
The Quai protocol achieves high transactional throughput by dividing transactional processing into independent shards. Each shard achieves shared total security via merged-mining. Adding more chains into the tree enables higher throughput, at the cost of increased cross-chain settlement times. Therefore, it is desirable for the network to activate only as few chains as are necessary to satisfy the users' demand for transactions.
As the number of transactions processed by the network increases, block propagation & processing time will increase (a.k.a. block acceptance time). This increase in block acceptance time results in higher probability of competing blocks produced within the same time, and thus short reorganizations (a.k.a. uncleed uncles) as the networks decides on the canonical set of blocks. The ratio of work committed to blocks that ultimately do not get accepted, can be measured as wasted work performed by miners. By measuring this waste, we can objectively determine the efficiency with which miners secure the network, which we refer to as "security efficiency".
This specification provides a mechanism for measuring the security efficiency of the network, so that when security efficiency becomes unacceptably low, the network can agree to add more chains to increase transactional capacity (at the expense of cross-chain settlement times) to improve security efficiency.
To measure the security efficiency of the network, nodes will need to compute the ratio of the amount of entropy which gets lost to uncle blocks vs the amount of entropy which gets accepted by canonical blocks. To facilitate this, each block needs to record these entropy measurements.
PoEM already describes the method of computing and recording entropy reduction in each block. That calculation is repeated below for completeness:
Uncle entropy calculation is slightly different. Since each block may reference multiple parallel uncles, the entropy for each should be accumulated.For N uncles, the uncle entropy of a block shall be computed by summing the entropy of each uncle hash:
where
Each node shall record recently uncled entropy and recently accepted entropy values for each chain it is participating in. Recentness of this measurement is achieved by applying an exponentially weighted moving average to the accepted/uncled entropy observed at each new block. This score can be computed iteratively with each new block added to the chain. First, the node will compute an exponentially weighted moving average of the uncle_entropy and accepted_entropy.
The weighted accepted & uncled entropies must be recorded in each chain, so that an aggregate security score can be computed in the prime chain of any node, regardless of which subordinate chains a node participates in.
In accordance with PoEM consensus, each node already measures the cumulativ
entropy reduction achieved by the work performed on every block. This entropy
is accumulated and referred to as ParentS
and
ParentSubDeltaS
.
In order for dominant chains to compute a security score across the network,
each chain will additionally need to record the uncled entropy and cumulative
uncled entropy,
In addition to as
type Header {
...
// The accepted entropy measurements are already a requirement from PoEM
ParentAcceptedS[3]: bigint, // prime/region/zone parent *accepted* entropy
ParentAcceptedSubDeltaS[2]: bigint, // prime/region subordinate cumulative *accepted* entropy
// This spec additionally requires uncled entropy measurements
ParentUncledS[3]: bigint, // prime/region/zone parent *uncled* entropy
ParentUncledSubDeltaS[2]: bigint, // prime/region subordinate cumulative *uncled* entropy
...
}
Before computing a security score, we must exponentially weight the cumulative entropies, to prevent the score from becoming overwhelmingly biased by old blocks. We can then use these weighted measurements to compute a security score.
First compute an error value
Next compute the exponentially weighted accepted entropy,
Note, for efficiency
S
values are recorded and computed in their log2 form, rounded to the nearest integer (aka bits).
In the above computations,
The following equation can be used to compute the security score,
A security score can be computed in the same way for any chain, but this
protocol is only interested in the global score, denoted as
When
The network will agree to add more chains to the tree, once all of the following conditions are met:
- all active chains have mined consecutive prime blocks confirming
$f_{global}$ exceeds theTREE_EXPANSION_THRESHOLD
-
TREE_EXPANSION_TRIGGER_WINDOW
consecutive prime blocks confirm$f_{global}$ after condition 1.
Once the expansion criteria have been met, the network will schedule expansion
to occur in the future. After TREE_EXPANSION_WAIT_COUNT
blocks have elapsed
since the block which finalized the decision to expand, blocks from the new
chains will be accepted by the network. The last prime block of the wait period
TREE_EXPANSION_WAIT_COUNT
will be refered to here on as the prime activation
block.
The Quai protocol defines a tree of blockchains of order 2. Initially, the tree is of degree 1: prime chain, with a single subordinate region chain, which has a single subordinate zone chain. As the network decides to add new chains, it will use the following algorithm to decide how many chains to add, and in which branches of the tree:
Algorithm to decide which chains to add:
1: if degree(zone) <= degree(region) then
2: add 1 chain to each zone
3: else then
4: add 1 region under prime
5: add degree(zone) zones under the new region
6: end if
For example, the table below gives the tree ontology after the first few expansions
Expansion no. | # regions in prime | # zones in each region |
---|---|---|
0 (genesis) | 1 | 1 |
1 | 1 | 2 |
2 | 2 | 2 |
3 | 2 | 3 |
4 | 3 | 3 |
5 | 3 | 4 |
6 | 4 | 4 |
. | . | . |
. | . | . |
. | . | . |
30 | 15 | 15 |
31 | 15 | 16 |
32 | 16 | 16 |
To mitigate migration challenges to the new chains, its important for the blockchains to stabilize and merge mine together for some time, before processing cross-chain transactions. To achieve this, we add a few constraints that must be satisfied before cross-chain transactions can be sent to these new chains.
First, the following sequence of events must occur:
- first, the new chain must mine a prime block that gets accepted by the network
- then the sending chain must mine a prime block committing to the new chain as an ancestor.
Additionally, at least TRANSACTION_WAIT_COUNT
prime blocks must have been
mined on-top of the new chain's first prime block.
Once these two conditions occur, the old chain may begin to process external transactions destined to the new chain. These conditions must be satisfied for any chain wishing to send to any of the newly added chains.
Once new chains have been activated, the activation block will be treated as the genesis block for all newly activated chains. The first block after genesis is built as an extension, with zone and optionally region parameters reset for the new chain.
The initial difficulty in each new chain shall be the difficulty of the genesis block divided by the number of chains in the network.
Note: the genesis block of the very first chain in the network can be viewed as the first expansion from a degree-0 tree to degree-1. All expansion logic is identical, even in this special case.
< TBD example diagram >
This specification works as long as miners record the uncles they witness. If miners choose not to record uncles, then the protocol cannot effectively measure uncled entropy. Therefore the incentive structure of the network should make sure that the dominant strategy for a miner is to record uncles, in lieu of any incentive they may have to prevent the network from expanding. This should not be difficult, but incentive mechanisms will be left for another QIP.
The above protocol for tree expansion is defined around a few adjustable parameters, given below:
This is the smoothing factor (range 0-1) used by each zone in its low-pass
filter to gather a long running average of the zone's security efficiency
score. Choosing a larger
Choose TREE_EXPANSION_FILTER_ALPHA = 0.9
This is the threshold (range 0-1) above which the
Choose TREE_EXPANSION_THRESHOLD = 0.5
Once all chains have confirmed TREE_EXPANSION_THRESHOLD
,
this is the number of consecutive prime blocks that
Choose TREE_EXPANSION_TRIGGER_WINDOW = 144 prime blocks (apprx 24hrs at 10m prime block time)
Once the network has confirmed the decision to expand the tree, this is the number of prime blocks to wait until the expansion is activated. This should be chosen to give node operators some time to adjust their infrastructure, if needed, to account for the upcoming network change.
Choose TREE_EXPANSION_WAIT_COUNT = 1024 prime blocks (apprx 1 week at 10m prime block time)
Once a new chain has been added to the network, no chain may sent cross-chain
transactions to it, until it has at least TRANSACTION_WAIT_COUNT
blocks built
upon the new chain's first coincident prime block.
Choose TRANSACTION_WAIT_COUNT = 1024 prime blocks (apprx 1 week at 10m prime block time)
This QIP licensed under the BSD 2-clause license.