[clock] waitUntil() completes immediately when block arrives (#475)

Previously it could take up to one second to complete
the future. This messed with the timings in the
integration tests and made them less predictable.
This commit is contained in:
markspanbroek 2023-07-13 11:19:45 +02:00 committed by GitHub
parent 6dd7e55719
commit 3879ec8e3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 25 additions and 7 deletions

View File

@ -10,9 +10,8 @@ type
method now*(clock: Clock): SecondsSince1970 {.base, upraises: [].} = method now*(clock: Clock): SecondsSince1970 {.base, upraises: [].} =
raiseAssert "not implemented" raiseAssert "not implemented"
method waitUntil*(clock: Clock, time: SecondsSince1970) {.base,async.} = method waitUntil*(clock: Clock, time: SecondsSince1970) {.base, async.} =
while clock.now() < time: raiseAssert "not implemented"
await sleepAsync(1.seconds)
proc withTimeout*(future: Future[void], proc withTimeout*(future: Future[void],
clock: Clock, clock: Clock,

View File

@ -12,9 +12,10 @@ type
subscription: Subscription subscription: Subscription
offset: times.Duration offset: times.Duration
started: bool started: bool
newBlock: AsyncEvent
proc new*(_: type OnChainClock, provider: Provider): OnChainClock = proc new*(_: type OnChainClock, provider: Provider): OnChainClock =
OnChainClock(provider: provider) OnChainClock(provider: provider, newBlock: newAsyncEvent())
proc start*(clock: OnChainClock) {.async.} = proc start*(clock: OnChainClock) {.async.} =
if clock.started: if clock.started:
@ -25,6 +26,7 @@ proc start*(clock: OnChainClock) {.async.} =
let blockTime = initTime(blck.timestamp.truncate(int64), 0) let blockTime = initTime(blck.timestamp.truncate(int64), 0)
let computerTime = getTime() let computerTime = getTime()
clock.offset = blockTime - computerTime clock.offset = blockTime - computerTime
clock.newBlock.fire()
if latestBlock =? (await clock.provider.getBlock(BlockTag.latest)): if latestBlock =? (await clock.provider.getBlock(BlockTag.latest)):
await onBlock(latestBlock) await onBlock(latestBlock)
@ -41,3 +43,8 @@ proc stop*(clock: OnChainClock) {.async.} =
method now*(clock: OnChainClock): SecondsSince1970 = method now*(clock: OnChainClock): SecondsSince1970 =
doAssert clock.started, "clock should be started before calling now()" doAssert clock.started, "clock should be started before calling now()"
toUnix(getTime() + clock.offset) toUnix(getTime() + clock.offset)
method waitUntil*(clock: OnChainClock, time: SecondsSince1970) {.async.} =
while (let difference = time - clock.now(); difference > 0):
clock.newBlock.clear()
discard await clock.newBlock.wait().withTimeout(chronos.seconds(difference))

View File

@ -29,6 +29,18 @@ ethersuite "On-Chain Clock":
await sleepAsync(chronos.seconds(1)) await sleepAsync(chronos.seconds(1))
check clock.now() > past check clock.now() > past
test "can wait until a certain time is reached by the chain":
let future = clock.now() + 42 # seconds
let waiting = clock.waitUntil(future)
discard await provider.send("evm_setNextBlockTimestamp", @[%future])
discard await provider.send("evm_mine")
check await waiting.withTimeout(chronos.milliseconds(100))
test "can wait until a certain time is reached by the wall-clock":
let future = clock.now() + 1 # seconds
let waiting = clock.waitUntil(future)
check await waiting.withTimeout(chronos.seconds(2))
test "raises when not started": test "raises when not started":
expect AssertionDefect: expect AssertionDefect:
discard OnChainClock.new(provider).now() discard OnChainClock.new(provider).now()

View File

@ -94,7 +94,7 @@ twonodessuite "Proving integration test", debug1=false, debug2=false:
break break
else: else:
await advanceToNextPeriod() await advanceToNextPeriod()
await sleepAsync(1.seconds) await sleepAsync(100.milliseconds)
check slotWasFreed check slotWasFreed
@ -186,7 +186,7 @@ multinodesuite "Simulate invalid proofs",
break break
else: else:
await advanceToNextPeriod() await advanceToNextPeriod()
await sleepAsync(1.seconds) await sleepAsync(100.milliseconds)
check slotWasFreed check slotWasFreed
@ -210,7 +210,7 @@ multinodesuite "Simulate invalid proofs",
break break
else: else:
await advanceToNextPeriod() await advanceToNextPeriod()
await sleepAsync(1.seconds) await sleepAsync(100.milliseconds)
check not slotWasFreed check not slotWasFreed