Skip to content

Commit

Permalink
block_scanner example improve
Browse files Browse the repository at this point in the history
  • Loading branch information
crazyministr committed Dec 14, 2023
1 parent 35e5e55 commit 7f86bf5
Showing 1 changed file with 48 additions and 24 deletions.
72 changes: 48 additions & 24 deletions examples/blocks/block_scanner.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import asyncio
import datetime
import logging
import time
import typing
from types import coroutine

from pytoniq_core.tlb.block import ExtBlkRef

from pytoniq.liteclient import LiteClient
from pytoniq_core.tlb import Block, ValueFlow, ShardAccounts
from pytoniq_core.tl import BlockIdExt


Expand All @@ -27,14 +22,20 @@ def __init__(self,
self.shards_storage = {}
self.blks_queue = asyncio.Queue()

async def run(self):
async def run(self, mc_seqno: int = None):
if not self.client.inited:
raise Exception('should init client first')
master_blk = self.mc_info_to_tl_blk(await self.client.get_masterchain_info())
shards = await self.client.get_all_shards_info(master_blk)
for shard in shards:

if mc_seqno is None:
master_blk: BlockIdExt = self.mc_info_to_tl_blk(await self.client.get_masterchain_info())
else:
master_blk, _ = await self.client.lookup_block(wc=-1, shard=-9223372036854775808, seqno=mc_seqno)

master_blk_prev, _ = await self.client.lookup_block(wc=-1, shard=-9223372036854775808, seqno=master_blk.seqno - 1)

shards_prev = await self.client.get_all_shards_info(master_blk_prev)
for shard in shards_prev:
self.shards_storage[self.get_shard_id(shard)] = shard.seqno
await self.blks_queue.put(shard)

while True:
await self.blks_queue.put(master_blk)
Expand All @@ -47,40 +48,62 @@ async def run(self):
while not self.blks_queue.empty():
await self.block_handler(self.blks_queue.get_nowait())

master_blk = self.mc_info_to_tl_blk(
await self.client.wait_masterchain_seqno(
seqno=master_blk.seqno + 1, timeout_ms=10000, schema_name='getMasterchainInfo', data={}
)
)
while True:
if master_blk.seqno + 1 == self.client.last_mc_block.seqno:
master_blk = self.client.last_mc_block
break
elif master_blk.seqno + 1 < self.client.last_mc_block.seqno:
master_blk, _ = await self.client.lookup_block(wc=-1, shard=-9223372036854775808, seqno=master_blk.seqno + 1)
break
await asyncio.sleep(0.1)

async def get_not_seen_shards(self, shard: BlockIdExt):
if self.shards_storage.get(self.get_shard_id(shard)) == shard.seqno:
return []
result = []
await self.blks_queue.put(shard)
return

full_blk = await self.client.raw_get_block_header(shard)
prev_ref = full_blk.info.prev_ref
if prev_ref.type_ == 'prev_blk_info': # only one prev block
prev: ExtBlkRef = prev_ref.prev
prev_shard = self.get_parent_shard(shard.shard) if full_blk.info.after_split else shard.shard
await self.get_not_seen_shards(BlockIdExt(
workchain=shard.workchain, seqno=prev.seqno, shard=shard.shard,
workchain=shard.workchain, seqno=prev.seqno, shard=prev_shard,
root_hash=prev.root_hash, file_hash=prev.file_hash
)
)
else:
prev1: ExtBlkRef = prev_ref.prev1
prev2: ExtBlkRef = prev_ref.prev2
await self.get_not_seen_shards(BlockIdExt(
workchain=shard.workchain, seqno=prev1.seqno, shard=shard.shard,
workchain=shard.workchain, seqno=prev1.seqno, shard=self.get_child_shard(shard.shard, left=True),
root_hash=prev1.root_hash, file_hash=prev1.file_hash
)
)
await self.get_not_seen_shards(BlockIdExt(
workchain=shard.workchain, seqno=prev2.seqno, shard=shard.shard,
workchain=shard.workchain, seqno=prev2.seqno, shard=self.get_child_shard(shard.shard, left=False),
root_hash=prev2.root_hash, file_hash=prev2.file_hash
)
)
return result

await self.blks_queue.put(shard)

def get_child_shard(self, shard: int, left: bool) -> int:
x = self.lower_bit64(shard) >> 1
if left:
return self.simulate_overflow(shard - x)
return self.simulate_overflow(shard + x)

def get_parent_shard(self, shard: int) -> int:
x = self.lower_bit64(shard)
return self.simulate_overflow((shard - x) | (x << 1))

@staticmethod
def simulate_overflow(x) -> int:
return (x + 2**63) % 2**64 - 2**63

@staticmethod
def lower_bit64(num: int) -> int:
return num & (~num + 1)

@staticmethod
def mc_info_to_tl_blk(info: dict):
Expand All @@ -96,8 +119,9 @@ async def handle_block(block: BlockIdExt):
return
print(block)
transactions = await client.raw_get_block_transactions_ext(block)
for transaction in transactions:
print(transaction.in_msg)
print(f"{len(transactions)=}")
# for transaction in transactions:
# print(transaction.in_msg)


client = LiteClient.from_mainnet_config(ls_i=14, trust_level=2, timeout=20)
Expand Down

0 comments on commit 7f86bf5

Please sign in to comment.