async def _add_diff_change(headers: List[RelayHeader]) -> None: print('Diff change') nonce = next(shared.NONCE) logger.info(f'\ndiff change {len(headers)} new headers,\n' f'first is {utils.format_header(headers[0])}\n' f'last is {utils.format_header(headers[-1])}\n') epoch_start = headers[0]['height'] - 2016 old_start_or_none, old_end_or_none = await asyncio.gather( bcoin_rpc.get_header_by_height(epoch_start), bcoin_rpc.get_header_by_height(epoch_start + 2015), ) # we know these casts won't fail old_start = cast(RelayHeader, old_start_or_none) old_end = cast(RelayHeader, old_end_or_none) logger.debug(f'old start is {old_start["hash_le"].hex()}') logger.debug(f'old end is {old_end["hash_le"].hex()}') headers_hex = ''.join(h['raw'].hex() for h in headers) tx = shared.make_call_tx( contract=config.get()['CONTRACT'], abi=relay_ABI, method='addHeadersWithRetarget', args=[old_start["raw"], old_end["raw"], headers_hex], nonce=nonce) asyncio.create_task(shared.sign_and_broadcast(tx))
async def _update_best_digest(new_best: RelayHeader) -> None: '''Send an ethereum transaction that marks a new best known chain tip''' nonce = next(shared.NONCE) will_succeed = False while not will_succeed: current_best_digest = await contract.get_best_block() current_best = cast( RelayHeader, await bcoin_rpc.get_header_by_hash(current_best_digest)) delta = new_best['height'] - current_best['height'] + 1 # find the latest block in current's history that is an ancestor of new is_ancestor = False ancestor = current_best originalAncestor = ancestor counter = 0 while True: is_ancestor = await contract.is_ancestor(ancestor['hash_le'], new_best['hash_le']) if is_ancestor: counter = 0 break ancestor = cast( RelayHeader, await bcoin_rpc.get_header_by_hash(ancestor['prevhash'])) counter = counter + 1 if counter > 200: ancestor = originalAncestor counter = 0 ancestor_le = ancestor['hash_le'] tx = shared.make_call_tx( contract=config.get()['CONTRACT'], abi=relay_ABI, method='markNewHeaviest', args=[ancestor_le, current_best["raw"], new_best["raw"], delta], nonce=nonce) try: result = await shared.CONNECTION.preflight_tx( tx, sender=config.get()['ETH_ADDRESS']) except RuntimeError: await asyncio.sleep(10) continue will_succeed = bool(int(result, 16)) if not will_succeed: await asyncio.sleep(10) logger.info(f'\nmarking new best\n' f'LCA is {ancestor["hash"].hex()}\n' f'previous best was {utils.format_header(current_best)}\n' f'new best is {utils.format_header(new_best)}\n') asyncio.create_task(shared.sign_and_broadcast(tx))
async def _add_headers(headers: List[RelayHeader]) -> None: logger.info(f'\nsending {len(headers)} new headers\n' f'first is {utils.format_header(headers[0])}\n' f'last is {utils.format_header(headers[-1])}\n') nonce = next(shared.NONCE) anchor_or_none = await bcoin_rpc.get_header_by_hash( headers[0]['prevhash'].hex()) anchor = cast(RelayHeader, anchor_or_none) headers_hex = ''.join(h['raw'].hex() for h in headers) tx = shared.make_call_tx(contract=config.get()['CONTRACT'], abi=relay_ABI, method='addHeaders', args=[anchor["raw"], headers_hex], nonce=nonce) asyncio.create_task(shared.sign_and_broadcast(tx))