polkascan / py-substrate-interface

Python Substrate Interface
https://polkascan.github.io/py-substrate-interface/
Apache License 2.0
239 stars 111 forks source link

"search_block_number" returning the block before expected block #359

Open RD4Fun opened 8 months ago

RD4Fun commented 8 months ago

the extensions "search_block_number" does not behave as I expected I expected the block closest to the search time image

Name: substrate-interface Version: 1.7.4 python 3.10 Code to generate output below

#!/usr/bin/env python3
from substrateinterface import SubstrateInterface
from substrateinterface.extensions import SubstrateNodeExtension
from datetime import datetime

# explorer
# https://polkadot.js.org/apps/?rpc=wss://entrypoint-finney.opentensor.ai:443#/explorer/query/1580950

def main():

    substrate = SubstrateInterface(url="wss://entrypoint-finney.opentensor.ai:443")
    substrate.register_extension(SubstrateNodeExtension(max_block_range=100))

    block_datetime = datetime(2023, 10, 27, 0, 0, 0,0)

    block_number = substrate.extensions.search_block_number(block_datetime=block_datetime,block_time=12)
    # All Timestamp extrinsics in block range #3 until #6
    dt={}
    blockstart = block_number -2
    extrinsics = substrate.extensions.filter_extrinsics(pallet_name="Timestamp", block_start=blockstart , block_end=block_number +3)

    for i, extrinsic in enumerate(extrinsics):
        timestamp = extrinsic.value['call']['call_args'][0]['value']
        dt[blockstart+i] = datetime.fromtimestamp(timestamp/1000).isoformat()
        print(f'block {blockstart+i} time {dt[blockstart+i]}')

if __name__ == "__main__":
    main()
RD4Fun commented 8 months ago

ran the code 48 hours later and it does not fault working on a example that always faults

arjanz commented 8 months ago

When you use the SubstrateNodeExtension it's not really deterministic, because it tries to find an acceptable block number after doing predictions based on the time between blocks. The tolerance is also one block time length (usually 6 seconds). You can see that logic here. Maybe this needs to be tweaks.

Turning on the DEBUG logging while reveal more info:

import logging
logging.basicConfig(level=logging.DEBUG)

You could also consider - if you have a Subsquid endpoint available for this network - to utilize the SubsquidExtension, this would be a more efficient and solution and has more predictable results.