Pi's response is pretty good. But, I've ran into rare situations where the +r/-r excludes tunix_s, and then it recurses until recursion depth limit exceeded. These adjustments fix that issue:
def iblock_near(tunix_s, left_block_tuple=(1, web3.eth.get_block(1).timestamp), right_block_tuple=(latest_block_number, web3.eth.get_block('latest').timestamp)):
left_block = left_block_tuple[0]
right_block = right_block_tuple[0]
left_timestamp = left_block_tuple[1]
right_timestamp = right_block_tuple[1]
if left_block == right_block:
return left_block
# Return the closer one, if we're already between blocks
if left_block == right_block - 1 or tunix_s <= left_timestamp or tunix_s >= right_timestamp:
return left_block if abs(tunix_s - left_block_tuple[1]) < abs(tunix_s - right_block_tuple[1]) else right_block
# K is how far inbetween left and right we're expected to be
k = (tunix_s - left_timestamp) / (right_timestamp - left_timestamp)
# We bound, to ensure logarithmic time even when guesses aren't great
k = min(max(k, 0.05), 0.95)
# We get the expected block number from K
expected_block = round(left_block + k * (right_block - left_block))
# Make sure to make some progress
expected_block = min(max(expected_block, left_block + 1), right_block - 1)
# Get the actual timestamp for that block
expected_block_timestamp = web3.eth.get_block(expected_block).timestamp
# Adjust bound using our estimated block
if expected_block_timestamp < tunix_s:
left_block = expected_block
left_timestamp = expected_block_timestamp
elif expected_block_timestamp > tunix_s:
right_block = expected_block
right_timestamp = expected_block_timestamp
else:
# Return the perfect match
return expected_block
# Recurse using tightened bounds
return iblock_near(tunix_s, (left_block, left_timestamp), (right_block, right_timestamp))
This modified version, caches the timestamp of 1 and latest, enforces logarithmic time convergence, and is thus safer to use and makes fewer requests as well.
tunix_s will also clamp to 1 or latest, if tunix_s is out-of-bounds for the eth network.