Fix likely unintentional unsigned integer wrap-around in GetBlockProofEquivalentTime(...) when to.nChainWork <= from.nChainWork.
Description:
int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, …)
contains the following code:
0int sign = 1;
1if (to.nChainWork > from.nChainWork) {
2…
3} else {
4 …
5 sign = -1;
6}
7…
8return sign * r.GetLow64();
r.GetLow64() is of type uint64_t.
Note that the types of the two operands in sign * r.GetLow64() differ in signedness.
Since uint64_t is wider than int the signed operand (sign) is converted to the unsigned type.
In the case of sign == -1 (to.nChainWork <= from.nChainWork) we wrap around and end up with 18446744073709551615 * r.GetLow64() (std::numeric_limits<uint64_t>::max() * r.GetLow64()) instead of the intended -1 * r.GetLow64().
Note however that another conversion takes place when the result is converted into the return type
(int64_t), so the resulting value should be the expected one (equivalent to -1 * r.GetLow64()).
In the case that this behaviour (wrap-around + relying on return type to fix) is intentional a comment should probably be added to indicate so :-)
GetBlockProofEquivalentTime(…) was introduced in f7303f97933be33e34d482cf8348d180c8da2a26. Friendly ping @sipa - intentional or not? :-)