Optimize votes lookups for recent checkpoints (#3673)
This commit is contained in:
@ -70,25 +70,6 @@ function upperLookup(${opts.historyTypeName} storage self, ${opts.keyTypeName} k
|
||||
uint256 pos = _upperBinaryLookup(self.${opts.checkpointFieldName}, key, 0, length);
|
||||
return pos == 0 ? 0 : _unsafeAccess(self.${opts.checkpointFieldName}, pos - 1).${opts.valueFieldName};
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the value in the most recent checkpoint with key lower or equal than the search key (similarly to
|
||||
* {upperLookup}), optimized for the case when the search key is known to be recent.
|
||||
*/
|
||||
function upperLookupRecent(${opts.historyTypeName} storage self, ${opts.keyTypeName} key) internal view returns (${opts.valueTypeName}) {
|
||||
uint256 length = self.${opts.checkpointFieldName}.length;
|
||||
uint256 offset = 1;
|
||||
|
||||
while (offset <= length && _unsafeAccess(self.${opts.checkpointFieldName}, length - offset).${opts.keyFieldName} > key) {
|
||||
offset <<= 1;
|
||||
}
|
||||
|
||||
uint256 low = 0 < offset && offset < length ? length - offset : 0;
|
||||
uint256 high = length - (offset >> 1);
|
||||
uint256 pos = _upperBinaryLookup(self.${opts.checkpointFieldName}, key, low, high);
|
||||
|
||||
return pos == 0 ? 0 : _unsafeAccess(self.${opts.checkpointFieldName}, pos - 1).${opts.valueFieldName};
|
||||
}
|
||||
`;
|
||||
|
||||
const legacyOperations = opts => `\
|
||||
@ -115,22 +96,28 @@ function getAtBlock(${opts.historyTypeName} storage self, uint256 blockNumber) i
|
||||
|
||||
/**
|
||||
* @dev Returns the value at a given block number. If a checkpoint is not available at that block, the closest one
|
||||
* before it is returned, or zero otherwise. Similarly to {upperLookup} but optimized for the case when the search
|
||||
* key is known to be recent.
|
||||
* before it is returned, or zero otherwise. Similar to {upperLookup} but optimized for the case when the searched
|
||||
* checkpoint is probably "recent", defined as being among the last sqrt(N) checkpoints where N is the number of
|
||||
* checkpoints.
|
||||
*/
|
||||
function getAtRecentBlock(${opts.historyTypeName} storage self, uint256 blockNumber) internal view returns (uint256) {
|
||||
function getAtProbablyRecentBlock(${opts.historyTypeName} storage self, uint256 blockNumber) internal view returns (uint256) {
|
||||
require(blockNumber < block.number, "Checkpoints: block not yet mined");
|
||||
uint32 key = SafeCast.toUint32(blockNumber);
|
||||
|
||||
uint256 length = self.${opts.checkpointFieldName}.length;
|
||||
uint256 offset = 1;
|
||||
|
||||
while (offset <= length && _unsafeAccess(self.${opts.checkpointFieldName}, length - offset).${opts.keyFieldName} > key) {
|
||||
offset <<= 1;
|
||||
uint256 low = 0;
|
||||
uint256 high = length;
|
||||
|
||||
if (length > 5) {
|
||||
uint256 mid = length - Math.sqrt(length);
|
||||
if (key < _unsafeAccess(self.${opts.checkpointFieldName}, mid)._blockNumber) {
|
||||
high = mid;
|
||||
} else {
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint256 low = offset < length ? length - offset : 0;
|
||||
uint256 high = length - (offset >> 1);
|
||||
uint256 pos = _upperBinaryLookup(self.${opts.checkpointFieldName}, key, low, high);
|
||||
|
||||
return pos == 0 ? 0 : _unsafeAccess(self.${opts.checkpointFieldName}, pos - 1).${opts.valueFieldName};
|
||||
|
||||
Reference in New Issue
Block a user