-
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, chains synchronize the beginning of the mine
phase with end of
validdate
phase of all parents on adjacent chains.
The wait
phase is making up for any variance in the other phases between chains.
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
c0: ... --------->|----->|--------->|-------->|----->|------->|---------> ...
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.
Miner a free to select a creation time for a new block at any time in any phase of a block cycle as long as
- the creation time of a block is strictly larger than the creation time of the parent and all adjacent parents and
- the creation time is not in the future, or more precisely is not in the future during validation.
From the second point it follows that the creation time can be from the validation
phase of the previous
block but not in the validation
phase of the block itself. Actually, depending on where the previous block
picked its validation time it can go back even further.
The current mining coordination code of a chainweb node picks the end of the wait
phase (start of the mining
phase) as block creation time. But it's important to not that miners are free to change/update that.
latency wait | mine latency wait | mine latency
c0: ... --------->|----->|--------->|-------->|----->|------->|---------> ...
... ...........................>
..............................>
................
^ ^
creationTime creationTime
What value should a miner choose? A rational miner will choose whatever results in the largest difficulty, for the above mentioned reasons. So, the difficulty adjustment algorithm must take this into account must align its goals with the this objective of the miners. There is on lower bound block times with respect to real world time. There's only an upper bound.
In order to minimize the wait
time, we need a way to measure the accumulative length of the wait
phase during an epoch. We don't have enough information to measure an absolute value for a single chain.
We only have the creation times and sum of the differences of the creation times is the wall-clock
time since epoch start:
sumblocks in epoch (creationTime - parentCreationTime) = creationTimelast block in epoch - epochStart
This does even hold if miners make really pathological choices for block creation times, like only increasing block times by microseconds starting from genesis. However, difficulty would become very low and thus there is an incentive for miners to choose values that result in long epoch times.
We can't measure the absolute value of the wait
time on a chain. But we can measure the difference in creation times between chains.
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.