runner workarounds for hardhat
This commit is contained in:
@@ -16,8 +16,9 @@ class Block(Base):
|
||||
|
||||
@property
|
||||
def timestamp(self) -> int:
|
||||
raw = self.data['timestamp']
|
||||
# noinspection PyTypeChecker
|
||||
return hexint(self.data['timestamp'])
|
||||
return raw if type(raw) is int else hexint(raw)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.height}_{self.hash.hex()[:5]}'
|
||||
|
||||
@@ -150,11 +150,16 @@ class BlockStateRunner:
|
||||
|
||||
while self.running:
|
||||
try:
|
||||
new_blocks = await w3.eth.filter("latest")
|
||||
for head in await new_blocks.get_new_entries():
|
||||
# polling mode is used primarily because Hardhat fails to deliver newHeads events after about an hour
|
||||
# unfortunately, hardhat also stops responding to eth_getBlockByHash. so instead, we use the standard (stupid)
|
||||
# 'latest' polling for blocks, and we push the entire block to the queue since apparently this is the only
|
||||
# rpc call Hardhat seems to consistently support. The worker must then detect the type of object pushed to the
|
||||
# work queue and either use the block directly or query for the block if the queue object is a hashcode.
|
||||
block = await w3.eth.get_block('latest')
|
||||
head = block['hash']
|
||||
if head != prev_blockhash:
|
||||
prev_blockhash = head
|
||||
await self.queue.put(head)
|
||||
await self.queue.put(block)
|
||||
log.debug(f'polled new block {hexstr(head)}')
|
||||
if not self.running:
|
||||
break
|
||||
@@ -187,7 +192,7 @@ class BlockStateRunner:
|
||||
except TimeoutError:
|
||||
# 1 second has passed without a new head. Run the postprocess callbacks to check for activated time-based triggers
|
||||
if prev_head is not None:
|
||||
await self.handle_time_tick(head)
|
||||
await self.handle_time_tick(prev_head)
|
||||
else:
|
||||
try:
|
||||
await self.handle_head(chain, head, w3)
|
||||
@@ -202,21 +207,26 @@ class BlockStateRunner:
|
||||
|
||||
|
||||
async def handle_head(self, chain, blockhash, w3):
|
||||
log.debug(f'processing block {hexstr(blockhash)}')
|
||||
# check blockhash type and convert
|
||||
try:
|
||||
block_data = blockhash
|
||||
blockhash = block_data['hash']
|
||||
parent = block_data['parentHash']
|
||||
height = block_data['number']
|
||||
except TypeError:
|
||||
response = await w3.provider.make_request('eth_getBlockByHash', [blockhash, False])
|
||||
block_data:dict = response['result']
|
||||
parent = bytes.fromhex(block_data['parentHash'][2:])
|
||||
height = int(block_data['number'], 0)
|
||||
log.debug(f'processing block {blockhash}')
|
||||
chain_id = chain.chain_id
|
||||
session = None
|
||||
try:
|
||||
blockhash = hexstr(blockhash)
|
||||
if self.state is not None and blockhash in self.state.by_hash:
|
||||
log.debug(f'block {blockhash} was already processed')
|
||||
return
|
||||
# block_data = await w3.eth.get_block(head['hash'], True)
|
||||
response = await w3.provider.make_request('eth_getBlockByHash', [blockhash, False])
|
||||
block_data = response['result']
|
||||
if block_data is None:
|
||||
log.warning(f'block data for {blockhash} was None')
|
||||
return # todo get block when hardhat stops responding to getBlockByHash
|
||||
block = Block(chain=chain_id, height=int(block_data['number'], 0),
|
||||
hash=bytes.fromhex(block_data['hash'][2:]), parent=bytes.fromhex(block_data['parentHash'][2:]), data=block_data)
|
||||
assert block_data is not None
|
||||
block = Block(chain=chain_id, height=height, hash=blockhash, parent=parent, data=block_data)
|
||||
latest_block.set(block)
|
||||
current_clock.get().set(block.timestamp)
|
||||
if self.state is None:
|
||||
@@ -329,8 +339,16 @@ class BlockStateRunner:
|
||||
async def handle_time_tick(self, blockhash):
|
||||
if current_blockstate.get() is None:
|
||||
return
|
||||
try:
|
||||
blockhash = blockhash['hash']
|
||||
except TypeError:
|
||||
pass
|
||||
# similar to handle_head, but we only call the postprocess events, since there was only a time tick and no new block data
|
||||
try:
|
||||
block = self.state.by_hash[blockhash]
|
||||
except KeyError:
|
||||
log.warning(f'No block data for {blockhash}. Aborting time tick.')
|
||||
return
|
||||
fork = self.state.fork(block)
|
||||
current_block.set(block)
|
||||
current_fork.set(fork)
|
||||
|
||||
Reference in New Issue
Block a user