-
Notifications
You must be signed in to change notification settings - Fork 93
Block Life Cycle and Difficulty Adjustment
The overall process of creating new blocks on a single chain is:
createPayload wait mine validate createPayload wait mine validate
|-------------->|----->|----->|--------->|-------------->|----->|----->|--------->| ...
where
-
createPaylaod
is the call to pact newBlock that assembles a new payload and executes Pact on it, -
wait
indicates that the chain is waiting for the parent headers on adjacent chains to become available, -
mine
means that miners are working to resolve the POW challenge, and -
validate
is the time it takes to propagate the and validate the block in the consensus network.
In a Chainweb, adjacent chains synchronize after the wait
and at the beginning of the mine
phase:
createPayload wait mine validate createPayload wait mine validate
... -------------->|----->|--------->|--------->|-------------->|----->|------->|---------> ...
... --------->|---------->|----->|--------->|-------------->|--------->|--------->|---------> ...
... ------------>|------->|------->|--------->|-------------->|------->|--------->|---------> ...
The wait phase is making up for any variance in the phases.
For the purpose of DA, we assume that createPayload
and the validate
phase are more or less constant across chains and we will refer to them jointly as latency
:
latency wait mine latency wait mine latency
... --------->|----->|--------->|-------->|----->|------->|---------> ...
... ---->|---------->|----->|-------->|--------->|--------->|--------> ...
... ------->|------->|------->|-------->|------->|------->|--------> ...
Difficulty Adjustment works by measuring the time that it takes to process a fixed number (120 on mainnet) of those block cycles, which is called an Epoch and adjusting the POW difficulty such that the expected time of an epoch matches the targeted time.[1]
When the measure epoch time is too short the new target is lower, and, conversely, when the measure epoch time is too big the target is increased. Without going into all details, the formula is roughly
newTarget = oldTarget * epochTime / targetedEpochTime
with difficulty = maxTarget / target
, for a given target.
Because chains synchronize with their adjacent chains during each block cycle, the wall-clock time for an epoch is mostly the same. The difference between chains are only in the order of the differences for a single block cycles time the diameter of the network. Assuming uniform distribution over the time of the epoch, on mainet with 10 chains the expected global difference is roughly 2/120
of the expected accumulated local differences.
Any discrepancy in the hash power or the targets between different chains takes a long time to adjust. Generally, that isn't an issue, because miners have an interest in accurate difficulties and are expected to distributed their hash power accordingly. If the relative difficulty between chains is too much off, chains become blocked often which increases the number of orphans and thus decreases the efficiency of mining. Also mining on chain with too low difficulty becomes a lottery with the actual hash power being less relevant for the outcome.
The goal of per chain difficulty adjustment is to minimize the time that chains are in the wait
phase. This is achieved by allowing for larger differences in the adjustments between chains. There are two approaches to per chain adjustments:
-
If all chains use the same hash algorithm, there is no reason why chains should have a different difficulty because hash power is automatically balanced between chains.[2]
In this case the goal is to adjust difficulty such that (a) the target epoch time is met and (b) and the difference of the difficulty between chains is minimized.
-
If chains use different hash algorithms Difficulty adjustment must be able to measure the time that chains are in the
wait
phase relative to other chains. Difficulty adjustment needs this information in order to be able to minimize the wait times.
During block creation and validation the following relevant block information is available:
- creation times of parent andadjacent parents,
- target of parent and adjacent parent,
- epoch start time of current chain and adjacent chains, and
- block height of current chain and adjacent chains.
In the first case, it is enough to compute the target using the global difficulty adjustment algorithm for the current and all adjacent chains and use the average.
The second case is more interesting and we focus on it in the following.
[TODO, more content coming soon...]
Chainweb uses a rather simple algorithm that just does an linear adjustment. There are more sophisticated approaches, like adjustments based on moving average or PID controllers. We found that the our approach works well enough and has the benefit of being simpler and more efficient.
Generally, one can think of other reason, beside the hash algorithm, why chains might be more or less efficient and should thus use different difficulties, but that does not apply to Chainweb in its current form.