def send_confirmation_block_history(*, block_identifier, ip_address, port, protocol): """ Send historical confirmation blocks (starting with the block_identifier) to the confirmation validator """ address = format_address(ip_address=ip_address, port=port, protocol=protocol) url = f'{address}/confirmation_blocks' valid_confirmation_block = get_valid_confirmation_block( block_identifier=block_identifier) while valid_confirmation_block: try: post(url=url, body=valid_confirmation_block) except Exception as e: capture_exception(e) logger.exception(e) block_identifier = get_message_hash( message=valid_confirmation_block['message']) valid_confirmation_block = get_valid_confirmation_block( block_identifier=block_identifier)
def send_signed_block(*, block, ip_address, port, protocol, url_path): """ Sign block and send to recipient """ signing_key = get_signing_key() node_identifier = get_verify_key(signing_key=signing_key) node_identifier = encode_verify_key(verify_key=node_identifier) message = sort_and_encode(block) signed_block = { 'block': block, 'node_identifier': node_identifier, 'signature': generate_signature(message=message, signing_key=signing_key) } node_address = format_address(ip_address=ip_address, port=port, protocol=protocol) url = f'{node_address}{url_path}' try: post(url=url, body=signed_block) except Exception as e: request_new_primary_validator() logger.exception(e)
def connect_to_primary_validator(*, primary_validator): """ Connect to a validator - used in the syncing process """ self_configuration = get_self_configuration(exception_class=RuntimeError) primary_validator_address = format_address( ip_address=primary_validator.ip_address, port=primary_validator.port, protocol=primary_validator.protocol, ) if is_connected_to_primary_validator( primary_validator_address=primary_validator_address, self_configuration=self_configuration): return signed_request = generate_signed_request(data={ 'ip_address': self_configuration.ip_address, 'port': self_configuration.port, 'protocol': self_configuration.protocol }, nid_signing_key=get_signing_key()) url = f'{primary_validator_address}/connection_requests' try: post(url=url, body=signed_request) except Exception as e: logger.exception(e) raise e
def send_primary_validator_updated_notices(): """ Send a notice to all validators that the banks primary validator has been updated - 200 response > validator is syncing to new primary validator - 400 response > validator is not syncing to new primary validator (can be deleted) """ self_configuration = get_self_configuration(exception_class=RuntimeError) primary_validator = self_configuration.primary_validator confirmation_validators = Validator.objects.all().exclude(node_identifier=primary_validator.node_identifier) data = { 'ip_address': primary_validator.ip_address, 'port': primary_validator.port, 'protocol': primary_validator.protocol } for confirmation_validator in confirmation_validators: signed_request = generate_signed_request( data=data, nid_signing_key=get_signing_key() ) node_address = format_address( ip_address=confirmation_validator.ip_address, port=confirmation_validator.port, protocol=confirmation_validator.protocol, ) url = f'{node_address}/primary_validator_updated' try: post(url=url, body=signed_request) except Exception as e: confirmation_validator.delete() logger.exception(e)
def send_connection_request(*, node, self_configuration): """ Send connection request to node """ node_address = format_address( ip_address=node.ip_address, port=node.port, protocol=node.protocol, ) signed_request = generate_signed_request(data={ 'ip_address': self_configuration.ip_address, 'port': self_configuration.port, 'protocol': self_configuration.protocol }, nid_signing_key=get_signing_key()) url = f'{node_address}/connection_requests' try: post(url=url, body=signed_request) except Exception as e: logger.exception(e) raise e
def send_confirmation_block_history_request(): """ Request missing blocks from the primary validator """ self_configuration = get_self_configuration(exception_class=RuntimeError) primary_validator = self_configuration.primary_validator address = format_address( ip_address=primary_validator.ip_address, port=primary_validator.port, protocol=primary_validator.protocol ) url = f'{address}/confirmation_block_history' signed_request = generate_signed_request( data={ 'block_identifier': cache.get(HEAD_BLOCK_HASH) }, nid_signing_key=get_signing_key() ) try: post(url=url, body=signed_request) except Exception as e: capture_exception(e) logger.exception(e)
def send_invalid_block_to_banks(*, confirmation_block): """ Send invalid block to banks This function is called by the confirmation validators only """ block = confirmation_block['block'] block_identifier = confirmation_block['block_identifier'] self_configuration = get_self_configuration(exception_class=RuntimeError) primary_validator_node_identifier = self_configuration.primary_validator.node_identifier self_configuration.primary_validator = None self_configuration.save() invalid_block = generate_signed_request(data={ 'block': block, 'block_identifier': block_identifier, 'primary_validator_node_identifier': primary_validator_node_identifier }, nid_signing_key=get_signing_key()) for bank in get_banks_with_active_confirmation_services(): address = format_address(ip_address=bank.ip_address, port=bank.port, protocol=bank.protocol) url = f'{address}/invalid_blocks' try: post(url=url, body=invalid_block) except Exception as e: logger.exception(e)
def send_signed_block(*, block, ip_address, port, protocol, url_path): """ Sign block and send to recipient """ network_signing_key = get_environment_variable('NETWORK_SIGNING_KEY') signing_key = SigningKey(network_signing_key, encoder=HexEncoder) node_identifier = get_verify_key(signing_key=signing_key) node_identifier = encode_verify_key(verify_key=node_identifier) message = sort_and_encode(block) signed_block = { 'block': block, 'node_identifier': node_identifier, 'signature': generate_signature(message=message, signing_key=signing_key) } node_address = format_address(ip_address=ip_address, port=port, protocol=protocol) url = f'{node_address}{url_path}' try: post(url=url, body=signed_block) except Exception as e: logger.exception(e)
def send_signed_post_request(*, data, ip_address, port, protocol, url_path): """Sign data and send to recipient""" signed_request = generate_signed_request(data=data, nid_signing_key=get_signing_key()) node_address = format_address(ip_address=ip_address, port=port, protocol=protocol) url = f'{node_address}{url_path}' try: post(url=url, body=signed_request) except Exception as e: capture_exception(e) logger.exception(e)
def send_confirmation_block_to_individual_confirmation_validator( *, confirmation_block, confirmation_validator_id, confirmation_validator_url): """ Send a confirmed block to a confirmation validator If NetworkException then delete that confirmation validator - occurs when the confirmation validator has gone offline or is not configured properly """ try: post(url=confirmation_validator_url, body=confirmation_block) except Exception as e: Validator.objects.filter(id=confirmation_validator_id).delete() capture_exception(e) logger.exception(e)
def send_confirmation_block_to_banks(*, confirmation_block): """ Send confirmed block to banks with active confirmation services This function is called by the confirmation validators only - primary validators send their confirmation blocks to the confirmation validators """ for bank in get_banks_with_active_confirmation_services(): address = format_address(ip_address=bank.ip_address, port=bank.port, protocol=bank.protocol) url = f'{address}/confirmation_blocks' try: post(url=url, body=confirmation_block) except Exception as e: logger.exception(e)
def send_signed_post_request(*, data, ip_address, port, protocol, url_path): """ Sign data and send to recipient """ network_signing_key = get_environment_variable('NETWORK_SIGNING_KEY') signing_key = SigningKey(network_signing_key, encoder=HexEncoder) signed_request = generate_signed_request( data=data, nid_signing_key=signing_key ) node_address = format_address(ip_address=ip_address, port=port, protocol=protocol) url = f'{node_address}{url_path}' try: post(url=url, body=signed_request) except Exception as e: logger.exception(e)
def send_upgrade_notices(*, requesting_banks_node_identifier): """ Description: - notice from a previous confirmation validator that they are now a primary validator - triggered from an /upgrade_request from the validators most trusted bank - banks that trust self more than their existing primary validator will set self as new primary validator - banks that do not trust self more than their existing primary validator will remain on their existing network and can therefore be deleted Responses: - 200 response > bank set self as new primary validator - 400 response > bank is remaining on their existing network (can be deleted) Notes: The requesting (most trusted) bank may be excluded from notice recipients since it will already receive the updated information from the /upgrade_request response """ banks = Bank.objects.all().exclude(node_identifier=requesting_banks_node_identifier) for bank in banks: signed_request = generate_signed_request( data={ 'bank_node_identifier': bank.node_identifier }, nid_signing_key=get_signing_key() ) node_address = format_address( ip_address=bank.ip_address, port=bank.port, protocol=bank.protocol, ) url = f'{node_address}/upgrade_notice' try: post(url=url, body=signed_request) except Exception as e: bank.delete() capture_exception(e) logger.exception(e)
def send_confirmation_block_to_confirmation_validators(*, confirmation_block): """ Send confirmed block to confirmation validators This function is called by the primary validator only - confirmation validators send their confirmation blocks to their banks """ # TODO: Optimize self_configuration = get_self_configuration(exception_class=RuntimeError) confirmation_validators = Validator.objects.exclude( node_identifier=self_configuration.node_identifier) for validator in confirmation_validators: address = format_address(ip_address=validator.ip_address, port=validator.port, protocol=validator.protocol) url = f'{address}/confirmation_blocks' try: post(url=url, body=confirmation_block) except Exception as e: logger.exception(e)
def send_request_to_node(signed_request): """ Send connection request to node """ node_address = format_address(ip_address='64.225.47.205', port=80, protocol='http') url = f'{node_address}/connection_requests' results = post(url=url, body=signed_request) if isinstance(results, dict): for k, v in results.items(): print(f'{k}: {v}') print(results)
def send_request_to_pv(signed_request): """ Send request to PV """ node_address = format_address(ip_address='64.225.47.205', port=None, protocol='http') url = f'{node_address}/bank_blocks' results = post(url=url, body=signed_request) if isinstance(results, dict): for k, v in results.items(): print(f'{k}: {v}') print(results) write_json(os.path.join(BLOCKS_DIR, 'bank-blocks-response.json'), results)
def send_block_to_bank(block): """ Send block to bank """ next_balance_lock = get_message_hash(message=block['message']) print(f'\nNext balance lock will be: {next_balance_lock}\n') bank_address = format_address(ip_address='167.99.173.247', port=None, protocol='http') url = f'{bank_address}/blocks' results = post(url=url, body=block) if isinstance(results, dict): for k, v in results.items(): print(f'{k}: {v}') write_json(os.path.join(BLOCKS_DIR, 'blocks-response.json'), results)
def send_request_to_cv(signed_request): """ Send request to CV """ node_address = format_address(ip_address='192.168.1.232', port=8000, protocol='http') url = f'{node_address}/upgrade_request' results = post(url=url, body=signed_request) if isinstance(results, dict): for k, v in results.items(): print(f'{k}: {v}') print(results) write_json( os.path.join(SIGNED_REQUESTS_DIR, 'upgrade-request-response.json'), results)
def send_request_to_bank(signed_request): """ Send request to bank """ node_address = format_address(ip_address='192.168.1.232', port=8000, protocol='http') url = f'{node_address}/validator_confirmation_services' results = post(url=url, body=signed_request) if isinstance(results, dict): for k, v in results.items(): print(f'{k}: {v}') print(results) write_json( os.path.join(SIGNED_REQUESTS_DIR, 'signed-validator-confirmation-services-response.json'), results)
def set_primary_validator(): """ Set the primary validator to the validator that is the: - most trusted - online - configured as a primary validator """ self_configuration = get_self_configuration(exception_class=RuntimeError) primary_validator = self_configuration.primary_validator primary_validator_candidates = get_primary_validator_candidates(current_primary_validator=primary_validator) for validator in primary_validator_candidates: signed_request = generate_signed_request( data={ 'validator_node_identifier': validator.node_identifier }, nid_signing_key=get_signing_key() ) node_address = format_address( ip_address=validator.ip_address, port=validator.port, protocol=validator.protocol, ) url = f'{node_address}/upgrade_request' try: validator_config = post(url=url, body=signed_request) if validator_config['node_type'] != PRIMARY_VALIDATOR: continue self_configuration.primary_validator = validator self_configuration.save() send_primary_validator_updated_notices.delay() send_primary_validator_updated_notification() return except Exception as e: logger.exception(e)