mirror of
https://github.com/codex-storage/nim-codex.git
synced 2025-01-24 11:49:11 +00:00
Refactors binary search
This commit is contained in:
parent
d07a5869ae
commit
6a7da7b086
@ -413,51 +413,72 @@ proc blockNumberAndTimestamp(provider: Provider, blockTag: BlockTag):
|
|||||||
|
|
||||||
(latestBlockNumber, latestBlock.timestamp)
|
(latestBlockNumber, latestBlock.timestamp)
|
||||||
|
|
||||||
|
proc estimateAverageBlockTime(provider: Provider): Future[UInt256] {.async.} =
|
||||||
|
let (latestBlockNumber, latestBlockTimestamp) =
|
||||||
|
await provider.blockNumberAndTimestamp(BlockTag.latest)
|
||||||
|
let (_, previousBlockTimestamp) =
|
||||||
|
await provider.blockNumberAndTimestamp(
|
||||||
|
BlockTag.init(latestBlockNumber - 1.u256))
|
||||||
|
trace "[estimateAverageBlockTime]:", latestBlockNumber = latestBlockNumber,
|
||||||
|
latestBlockTimestamp = latestBlockTimestamp,
|
||||||
|
previousBlockTimestamp = previousBlockTimestamp
|
||||||
|
return latestBlockTimestamp - previousBlockTimestamp
|
||||||
|
|
||||||
|
proc binarySearchFindClosestBlock(provider: Provider,
|
||||||
|
epochTime: int,
|
||||||
|
low: BlockTag,
|
||||||
|
high: BlockTag): Future[BlockTag] {.async.} =
|
||||||
|
let (_, lowTimestamp) =
|
||||||
|
await provider.blockNumberAndTimestamp(low)
|
||||||
|
let (_, highTimestamp) =
|
||||||
|
await provider.blockNumberAndTimestamp(high)
|
||||||
|
if abs(lowTimestamp.truncate(int) - epochTime) <
|
||||||
|
abs(highTimestamp.truncate(int) - epochTime):
|
||||||
|
return low
|
||||||
|
else:
|
||||||
|
return high
|
||||||
|
|
||||||
|
proc binarySearchBlockNumberForEpoch(provider: Provider,
|
||||||
|
epochTime: UInt256,
|
||||||
|
latestBlockNumber: UInt256):
|
||||||
|
Future[BlockTag] {.async.} =
|
||||||
|
var low = 0.u256
|
||||||
|
var high = latestBlockNumber
|
||||||
|
|
||||||
|
trace "[binarySearchBlockNumberForEpoch]:", low = low, high = high
|
||||||
|
while low <= high:
|
||||||
|
let mid = (low + high) div 2.u256
|
||||||
|
let (midBlockNumber, midBlockTimestamp) =
|
||||||
|
await provider.blockNumberAndTimestamp(BlockTag.init(mid))
|
||||||
|
|
||||||
|
if midBlockTimestamp < epochTime:
|
||||||
|
low = mid + 1.u256
|
||||||
|
elif midBlockTimestamp > epochTime:
|
||||||
|
high = mid - 1.u256
|
||||||
|
else:
|
||||||
|
return BlockTag.init(midBlockNumber)
|
||||||
|
await provider.binarySearchFindClosestBlock(
|
||||||
|
epochTime.truncate(int), BlockTag.init(low), BlockTag.init(high))
|
||||||
|
|
||||||
proc blockNumberForEpoch(provider: Provider, epochTime: int64): Future[BlockTag]
|
proc blockNumberForEpoch(provider: Provider, epochTime: int64): Future[BlockTag]
|
||||||
{.async.} =
|
{.async.} =
|
||||||
let avgBlockTime = 13.u256
|
let avgBlockTime = await provider.estimateAverageBlockTime()
|
||||||
|
trace "[blockNumberForEpoch]:", avgBlockTime = avgBlockTime
|
||||||
let epochTimeUInt256 = epochTime.u256
|
let epochTimeUInt256 = epochTime.u256
|
||||||
let (latestBlockNumber, latestBlockTimestamp) =
|
let (latestBlockNumber, latestBlockTimestamp) =
|
||||||
await blockNumberAndTimestamp(provider, BlockTag.latest)
|
await provider.blockNumberAndTimestamp(BlockTag.latest)
|
||||||
|
|
||||||
|
trace "[blockNumberForEpoch]:", latestBlockNumber = latestBlockNumber,
|
||||||
|
latestBlockTimestamp = latestBlockTimestamp
|
||||||
|
|
||||||
let timeDiff = latestBlockTimestamp - epochTimeUInt256
|
let timeDiff = latestBlockTimestamp - epochTimeUInt256
|
||||||
let blockDiff = timeDiff div avgBlockTime
|
let blockDiff = timeDiff div avgBlockTime
|
||||||
let estimatedBlockNumber = latestBlockNumber - blockDiff
|
|
||||||
|
|
||||||
let (estimatedBlockTimestamp, _) = await blockNumberAndTimestamp(
|
if blockDiff >= latestBlockNumber:
|
||||||
provider, BlockTag.init(estimatedBlockNumber))
|
return BlockTag.earliest
|
||||||
|
|
||||||
var low = 0.u256
|
return await provider.binarySearchBlockNumberForEpoch(
|
||||||
var high = latestBlockNumber
|
epochTimeUInt256, latestBlockNumber)
|
||||||
if estimatedBlockTimestamp < epochTimeUInt256:
|
|
||||||
low = estimatedBlockNumber
|
|
||||||
else:
|
|
||||||
high = estimatedBlockNumber
|
|
||||||
|
|
||||||
while low <= high:
|
|
||||||
let mid = (low + high) div 2
|
|
||||||
let (midBlockTimestamp, midBlockNumber) =
|
|
||||||
await blockNumberAndTimestamp(provider, BlockTag.init(mid))
|
|
||||||
|
|
||||||
if midBlockTimestamp < epochTimeUInt256:
|
|
||||||
low = mid + 1
|
|
||||||
elif midBlockTimestamp > epochTimeUInt256:
|
|
||||||
high = mid - 1
|
|
||||||
else:
|
|
||||||
return BlockTag.init(midBlockNumber)
|
|
||||||
|
|
||||||
let (_, lowTimestamp) = await blockNumberAndTimestamp(
|
|
||||||
provider, BlockTag.init(low))
|
|
||||||
let (_, highTimestamp) = await blockNumberAndTimestamp(
|
|
||||||
provider, BlockTag.init(high))
|
|
||||||
try:
|
|
||||||
if abs(lowTimestamp.stint(256) - epochTimeUInt256.stint(256)) <
|
|
||||||
abs(highTimestamp.stint(256) - epochTimeUInt256.stint(256)):
|
|
||||||
BlockTag.init(low)
|
|
||||||
else:
|
|
||||||
BlockTag.init(high)
|
|
||||||
except ValueError as e:
|
|
||||||
raise newException(EthersError, fmt"Conversion error: {e.msg}")
|
|
||||||
|
|
||||||
method queryPastSlotFilledEvents*(
|
method queryPastSlotFilledEvents*(
|
||||||
market: OnChainMarket,
|
market: OnChainMarket,
|
||||||
@ -483,9 +504,9 @@ method queryPastSlotFilledEvents*(
|
|||||||
fromTime: int64): Future[seq[SlotFilled]] {.async.} =
|
fromTime: int64): Future[seq[SlotFilled]] {.async.} =
|
||||||
|
|
||||||
convertEthersError:
|
convertEthersError:
|
||||||
let fromBlock = await blockNumberForEpoch(market.contract.provider,
|
let fromBlock =
|
||||||
fromTime)
|
await market.contract.provider.blockNumberForEpoch(fromTime)
|
||||||
|
trace "queryPastSlotFilledEvents fromTime", fromTime=fromTime, fromBlock=fromBlock
|
||||||
return await market.queryPastSlotFilledEvents(fromBlock)
|
return await market.queryPastSlotFilledEvents(fromBlock)
|
||||||
|
|
||||||
method queryPastStorageRequestedEvents*(
|
method queryPastStorageRequestedEvents*(
|
||||||
|
@ -128,15 +128,19 @@ proc epochForDurationBackFromNow(duration: times.Duration): int64 =
|
|||||||
return now - duration.inSeconds
|
return now - duration.inSeconds
|
||||||
|
|
||||||
proc restoreHistoricalState(validation: Validation) {.async} =
|
proc restoreHistoricalState(validation: Validation) {.async} =
|
||||||
|
trace "Restoring historical state..."
|
||||||
let startTimeEpoch = epochForDurationBackFromNow(MaxStorageRequestDuration)
|
let startTimeEpoch = epochForDurationBackFromNow(MaxStorageRequestDuration)
|
||||||
let slotFilledEvents = await validation.market.queryPastSlotFilledEvents(
|
let slotFilledEvents = await validation.market.queryPastSlotFilledEvents(
|
||||||
fromTime = startTimeEpoch)
|
fromTime = startTimeEpoch)
|
||||||
|
trace "Found slot filled events", numberOfSlots = slotFilledEvents.len
|
||||||
for event in slotFilledEvents:
|
for event in slotFilledEvents:
|
||||||
let slotId = slotId(event.requestId, event.slotIndex)
|
let slotId = slotId(event.requestId, event.slotIndex)
|
||||||
if validation.shouldValidateSlot(slotId):
|
if validation.shouldValidateSlot(slotId):
|
||||||
trace "Adding slot", slotId
|
trace "Adding slot [historical]", slotId
|
||||||
validation.slots.incl(slotId)
|
validation.slots.incl(slotId)
|
||||||
|
trace "Removing slots that have ended..."
|
||||||
await removeSlotsThatHaveEnded(validation)
|
await removeSlotsThatHaveEnded(validation)
|
||||||
|
trace "Historical state restored", numberOfSlots = validation.slots.len
|
||||||
|
|
||||||
proc start*(validation: Validation) {.async.} =
|
proc start*(validation: Validation) {.async.} =
|
||||||
validation.periodicity = await validation.market.periodicity()
|
validation.periodicity = await validation.market.periodicity()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user