Work
Work is a quantity of hash operations: 1 unit of work means computing the hash of one Block header.
In a proof-of-work blockchain, each State specifies a target,
which the next block's hash must not exceed. The expected amount of work
required to find such a hash is 2^256 / target
; this is known as the
difficulty. (Note that this is slightly different from the notion of
difficulty in Bitcoin.)
For example, if the target is 2^255
(i.e. it has a leading 1), then there is a
50% chance that any random hash will exceed the target. Thus, the difficulty—
the expected number of hashes—is 2. Conversely, if the difficulty is 1.015 x
2^65
(approximately what it was for Block 500,000), this corresponds to a
target of 1.965 x 2^190
.
Difficulty Adjustment
To maintain an average block time of 10 minutes, the difficulty must be regularly adjusted. Sia uses a continuous difficulty adjustment algorithm known as "Oak." First, we subtract the actual time elapsed since genesis from the expected time (that is, 10 minutes times the block height), and this delta is squared and scaled such that a delta of 10,000 seconds translates to a adjustment of 10 seconds. This adjustment, applied to the baseline 10 minute block time, yields the desired block time. For example, a delta of 10,000 seconds will result in a desired block time of 610 seconds. Finally, we estimate the current hashrate (by accumulating the total time and total work in the State and subjecting them to exponential decay to yield a strong recency bias), and multiply it by the desired block time to get the new difficulty.
In v1
Work in v1 was almost always represented in terms of a target, rather than a difficulty. For example, states did not have a "total work" field, but rather a "depth," representing the target hash that could theoretically be satisfied by adding up all of the work in the chain. To update the depth, both it and the block's hash were converted to work, added together, and then converted back to a target. Due to rounding, this produces slightly different results than adding work values directly; consequently, nodes that deal with both v1 and v2 states must explicitly store both representations, rather than converting one to the other as needed.