Skip to content

Commit

Permalink
add calculate avg block time interval
Browse files Browse the repository at this point in the history
  • Loading branch information
zakir-code committed Oct 17, 2023
1 parent 392f7e1 commit ffafba7
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 20 deletions.
5 changes: 3 additions & 2 deletions examples/scan.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
if __name__ == '__main__':
logging.config.dictConfig(yaml.safe_load(open('../.logging.yaml', 'r')))
rpc_url = "http://127.0.0.1:26657"
ws_client = ScanBlock(endpoint_url=rpc_url)
ws_client.start()
scan = ScanBlock(endpoint_url=rpc_url)
block_time_interval = scan.avg_block_time_interval()
scan.start(block_interval_ms=int(block_time_interval * 1000))
15 changes: 14 additions & 1 deletion fxsdk/client/grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def query_gas_prices(self) -> [Coin]:
return parse_coins(response.minimum_gas_price)

def query_block_by_height(self, height: int) -> Block:
response = TendermintClient(self.channel).GetBlockByHeight(GetBlockByHeightRequest(height))
response = TendermintClient(self.channel).GetBlockByHeight(GetBlockByHeightRequest(height=height))
return response.block

def query_latest_block(self) -> Block:
Expand All @@ -124,6 +124,19 @@ def query_node_info(self) -> DefaultNodeInfo:
response = TendermintClient(self.channel).GetNodeInfo(GetNodeInfoRequest())
return response.default_node_info

def avg_block_time_interval(self, block_interval: int = 2000) -> float:
latest_block = self.query_latest_block()
latest_block_height = latest_block.header.height
latest_block_time = latest_block.header.time.seconds
if latest_block_height > block_interval:
block = self.query_block_by_height(latest_block_height - block_interval)
else:
block = self.query_block_by_height(1)
block_interval = latest_block_height - 1
block_time = block.header.time.seconds
block_time_interval = (latest_block_time - block_time) / block_interval
return float(format(block_time_interval, '.3f'))

def query_tx(self, tx_hash: str) -> GetTxResponse:
return TxClient(self.channel).GetTx(GetTxRequest(hash=tx_hash))

Expand Down
16 changes: 16 additions & 0 deletions fxsdk/client/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import requests
import ujson

from datetime import datetime
from typing import Optional, Dict
from requests.sessions import HTTPAdapter
from urllib3.util.retry import Retry
Expand Down Expand Up @@ -123,6 +124,21 @@ def _handle_response(response) -> Dict:
except ValueError:
raise RPCException('Invalid Response: %s' % response.text)

def avg_block_time_interval(self, block_interval: int = 2000) -> float:
latest_block = self.get_block()
latest_block_time = latest_block.get('block', {}).get('header', {}).get('time', None)
latest_block_height = int(latest_block.get('block', {}).get('header', {}).get('height', None))
if latest_block_height > block_interval:
block = self.get_block(latest_block_height - block_interval)
else:
block = self.get_block(1)
block_interval = latest_block_height - 1
block_time = block.get('block', {}).get('header', {}).get('time', None)
latest_block_time = datetime.fromisoformat(latest_block_time)
block_time = datetime.fromisoformat(block_time)
block_time_interval = (latest_block_time.timestamp() - block_time.timestamp()) / block_interval
return float(format(block_time_interval, '.3f'))

def get_abci_info(self) -> Dict:
return self._request('abci_info')

Expand Down
20 changes: 7 additions & 13 deletions fxsdk/client/scan.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,40 +11,34 @@ class ScanException(Exception):


class ScanBlock(HttpRpcClient):
def __init__(self, endpoint_url, block_interval_ms: int = 500):
super().__init__(endpoint_url)
self._start_block_height = -1
self._block_interval_ms = block_interval_ms

def start(self, start_block_height: int = -1):
if start_block_height > 0:
self._start_block_height = start_block_height
else:
def start(self, block_interval_ms=500, start_block_height: int = -1):
if start_block_height <= 0:
status = self.get_status()
if status.get('sync_info', {}).get('catching_up', True):
raise ScanException("node is catching up")
latest_block_height = status.get('sync_info', {}).get('latest_block_height', 1)
self._start_block_height = int(latest_block_height)
start_block_height = int(latest_block_height)
while True:
try:
block_result = self.get_block_results(self._start_block_height)
block_result = self.get_block_results(start_block_height)
txs_results = block_result.get('txs_results', [])
txs_results = txs_results if txs_results else []
txs = []
if len(txs_results) > 0:
block = self.get_block(self._start_block_height)
block = self.get_block(start_block_height)
base64_txs = block.get('block', {}).get('data', {}).get('txs', [])
for base64_tx in base64_txs:
tx = new_tx_from_base64(base64_tx)
txs.append(tx)
block_events = block_result.get('finalize_block_events', [])
block_height = block_result.get('height', 0)
self.process_new_block(block_height, block_events, txs_results, txs)
self._start_block_height += 1
start_block_height += 1
except RPCException as e:
self._log.debug(f"rpc exception: {e}")
continue
time.sleep(self._block_interval_ms / 1000)
time.sleep(block_interval_ms / 1000)

def process_new_block(self, block_height: int, block_events: [Dict], txs_result: [Dict], txs: [Tx]):
self._log.info(
Expand Down
12 changes: 12 additions & 0 deletions tests/test_grpc_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ def test_query_node_info(self):
res = grpc_cli.query_node_info()
print(res)

def test_query_latest_block(self):
res = grpc_cli.query_latest_block()
print(res)

def test_query_block_by_height(self):
res = grpc_cli.query_block_by_height(height=1)
print(res)

def test_avg_block_time_interval(self):
res = grpc_cli.avg_block_time_interval()
print(res)


if __name__ == '__main__':
unittest.main()
14 changes: 10 additions & 4 deletions tests/test_http_query.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import asyncio
import json
import logging.config
import unittest
from typing import Dict

import yaml

from fxsdk.client.http import HttpRpcClient, AsyncHttpRpcClient
from fxsdk.client.websockets import WebsocketRpcClient
from fxsdk.msg import event
Expand All @@ -21,6 +18,16 @@ def test_get_block_result(self):
print(block_res)
assert block_res

def test_get_block(self):
block = rpc_client.get_block()
print(json.dumps(block, indent=2))
assert block

def test_avg_block_time_interval(self):
res = rpc_client.avg_block_time_interval()
print(res)
assert res


class TestWebsocketRpcClient(unittest.IsolatedAsyncioTestCase):

Expand All @@ -29,7 +36,6 @@ async def callback(msg: Dict):
print("msg", json.dumps(msg))

async def test_get_block_result(self):
logging.config.dictConfig(yaml.safe_load(open('../.logging.yaml', 'r')))
loop = asyncio.get_event_loop()
ws_client = await WebsocketRpcClient.create(endpoint_url=rpc_url, loop=loop, callback=self.callback)
await ws_client.get_status()
Expand Down

0 comments on commit ffafba7

Please sign in to comment.