mirror of
https://github.com/status-im/nim-dagger.git
synced 2025-01-10 06:36:06 +00:00
df6b9c6760
* Workaround for Hardhat timestamp bug Likely due to a Hardhat bug in which the callbacks for subscription events are called and awaited before updating its local understanding of the last block time, Hardhat will report a block time in the `newHeads` event that is generally 1 second before the time reported from `getLatestBlock.timestamp`. This was causing issues with the OnChainClock's offset and therefore the `now()` used by the `OnChainClock` would sometimes be off by a second (or more), causing tests to fail. This commit introduce a `codex_use_hardhat` compilation flag, that when set, will always get the latest block timestamp from Hardhat via the `getLatestBlock.timestamp` RPC call for `OnChainClock.now` calls. Otherwise, the last block timestamp reported in the `newHeads` event will be used. Update the docker dist tests compilation flag for simulated proof failures (it was not correct), and explicitly add the `codex_use_hardhat=false` for clarity. * enable simulated proof failures for coverage * comment out failing test on linux -- will be replaced * bump codex contracts eth * add back clock offset for non-hardhat cases * bump codex-contracts-eth increases pointer by 67 blocks each period increase * Add `codex_use_hardhat` flag to coverage tests
71 lines
2.2 KiB
Nim
71 lines
2.2 KiB
Nim
import std/times
|
|
import pkg/ethers
|
|
import pkg/chronos
|
|
import pkg/stint
|
|
import ../clock
|
|
import ../conf
|
|
|
|
export clock
|
|
|
|
logScope:
|
|
topics = "contracts clock"
|
|
|
|
type
|
|
OnChainClock* = ref object of Clock
|
|
provider: Provider
|
|
subscription: Subscription
|
|
offset: times.Duration
|
|
started: bool
|
|
newBlock: AsyncEvent
|
|
lastBlockTime: UInt256
|
|
|
|
proc new*(_: type OnChainClock, provider: Provider): OnChainClock =
|
|
OnChainClock(provider: provider, newBlock: newAsyncEvent())
|
|
|
|
method start*(clock: OnChainClock) {.async.} =
|
|
if clock.started:
|
|
return
|
|
|
|
proc onBlock(blck: Block) {.upraises:[].} =
|
|
let blockTime = initTime(blck.timestamp.truncate(int64), 0)
|
|
let computerTime = getTime()
|
|
clock.offset = blockTime - computerTime
|
|
clock.lastBlockTime = blck.timestamp
|
|
clock.newBlock.fire()
|
|
|
|
if latestBlock =? (await clock.provider.getBlock(BlockTag.latest)):
|
|
onBlock(latestBlock)
|
|
|
|
clock.subscription = await clock.provider.subscribe(onBlock)
|
|
clock.started = true
|
|
|
|
method stop*(clock: OnChainClock) {.async.} =
|
|
if not clock.started:
|
|
return
|
|
|
|
await clock.subscription.unsubscribe()
|
|
clock.started = false
|
|
|
|
method now*(clock: OnChainClock): SecondsSince1970 =
|
|
when codex_use_hardhat:
|
|
# hardhat's latest block.timestamp is usually 1s behind the block timestamp
|
|
# in the newHeads event. When testing, always return the latest block.
|
|
try:
|
|
if queriedBlock =? (waitFor clock.provider.getBlock(BlockTag.latest)):
|
|
trace "using last block timestamp for clock.now",
|
|
lastBlockTimestamp = queriedBlock.timestamp.truncate(int64),
|
|
cachedBlockTimestamp = clock.lastBlockTime.truncate(int64)
|
|
return queriedBlock.timestamp.truncate(int64)
|
|
except CatchableError as e:
|
|
warn "failed to get latest block timestamp", error = e.msg
|
|
return clock.lastBlockTime.truncate(int64)
|
|
|
|
else:
|
|
doAssert clock.started, "clock should be started before calling now()"
|
|
return 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))
|