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 test_invalid_account_number(client, account, self_configuration): client.patch_json( reverse('account-detail', args=[account.account_number + 'abcdef']), generate_signed_request(data={'trust': 100}, nid_signing_key=get_signing_key()), expected=HTTP_404_NOT_FOUND, )
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)
async def test_crawl_status_async(client, confirmation_validator_configuration, celery_worker): communicator = WebsocketCommunicator( CrawlStatusConsumer, 'ws/crawl_status' ) connected, subprotocol = await communicator.connect() assert connected await sync_to_async( client.post_json )( reverse('crawl-list'), generate_signed_request( data={ 'crawl': CRAWL_COMMAND_START }, nid_signing_key=get_signing_key() ), expected=HTTP_200_OK ) async_response = await communicator.receive_json_from(timeout=3) await communicator.disconnect() crawl_status = async_response['payload'] assert async_response['notification_type'] == CRAWL_STATUS_NOTIFICATION assert crawl_status['crawl_last_completed'] assert crawl_status['crawl_status'] == CRAWL_STATUS_NOT_CRAWLING
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 run(send_to_node=False): """ Generate signed PATCH request """ # Signed request sk = read_signing_key_file(os.path.join(SIGNING_KEY_DIR, 'bank_nid')) payload = { 'trust': 76.26 } target_nid = BANK_NID_ACCOUNT_NUMBER signed_request = generate_signed_request( data=payload, nid_signing_key=sk ) if send_to_node: send_request_to_node(signed_request, target_nid) write_json( os.path.join(SIGNED_REQUESTS_DIR, 'bank-patch-request.json'), signed_request )
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 run(send_to_cv=False): """ Generate primary validator updated notice (from bank) """ # Signed request sk = read_signing_key_file(os.path.join(SIGNING_KEY_DIR, 'bank_nid')) new_pv_data = { 'ip_address': '192.168.1.20', 'port': '8000', 'protocol': 'http' } signed_request = generate_signed_request( data=new_pv_data, nid_signing_key=sk ) if send_to_cv: send_request_to_cv(signed_request) write_json( os.path.join(SIGNED_REQUESTS_DIR, 'primary-validator-updated-request.json'), signed_request )
def validator_connection_requests_signed_request(validator, signing_key): yield generate_signed_request(data={ 'ip_address': validator.ip_address, 'port': validator.port, 'protocol': validator.protocol, }, nid_signing_key=signing_key)
def bank_connection_requests_signed_request(bank, signing_key): yield generate_signed_request(data={ 'ip_address': bank.ip_address, 'port': bank.port, 'protocol': bank.protocol, }, nid_signing_key=signing_key)
async def test_validator_confirmation_service_post_async( client, validator, signing_key): communicator = WebsocketCommunicator(ValidatorConfirmationServiceConsumer, 'ws/validator_confirmation_services') connected, subprotocol = await communicator.connect() assert connected start = datetime.now().isoformat() end = (datetime.now() + timedelta(days=2)).isoformat() payload = generate_signed_request(data={ 'start': start, 'end': end }, nid_signing_key=signing_key) response = await sync_to_async(client.post_json)( reverse('validatorconfirmationservice-list'), payload, expected=HTTP_201_CREATED) communicator_response = await communicator.receive_json_from() assert response['end'][:-1] == end assert response['start'][:-1] == start assert response['validator'] == str(validator.pk) assert communicator_response == { 'notification_type': VALIDATOR_CONFIRMATION_SERVICE_NOTIFICATION, 'payload': { 'bank_node_identifier': validator.node_identifier, 'validator_confirmation_service': response } } await communicator.disconnect()
def crawl_request(client, command, status): return client.post_json( reverse('crawl-list'), generate_signed_request(data={'crawl': command}, nid_signing_key=get_signing_key()), expected=status, )
def test_banks_post_201_confirmation_validator( client, validator_connection_request_data, signing_key, self_configuration, requests_mock): primary_validator = PrimaryValidatorConfigurationSerializer( self_configuration.primary_validator) validator_connection_request_data[ 'primary_validator'] = primary_validator.data address = format_address( ip_address=validator_connection_request_data['ip_address'], port=validator_connection_request_data.get('port'), protocol=validator_connection_request_data['protocol']) requests_mock.get(f'{address}/config', json=validator_connection_request_data) response = client.post_json(reverse('connection_requests-list'), generate_signed_request( data=validator_connection_request_data, nid_signing_key=signing_key, ), expected=status.HTTP_201_CREATED) assert response == {} assert Validator.objects.get( ip_address=validator_connection_request_data['ip_address'])
def sign_block_to_confirm_and_update_head_block_hash(*, block, existing_accounts, new_accounts): """ Sign block to confirm validity Update HEAD_BLOCK_HASH """ try: head_block_hash = cache.get(HEAD_BLOCK_HASH) message = { 'block': block, 'block_identifier': head_block_hash, 'updated_balances': format_updated_balances(existing_accounts, new_accounts) } confirmation_block = generate_signed_request( data=message, nid_signing_key=get_signing_key() ) message_hash = get_message_hash(message=message) cache.set(HEAD_BLOCK_HASH, message_hash, None) return confirmation_block, message_hash except Exception as e: capture_exception(e) logger.exception(e)
def set_primary_validator(client, self_configuration, signing_key, status): return client.post_json( reverse('upgrade_notice-list'), generate_signed_request( data={'bank_node_identifier': self_configuration.node_identifier}, nid_signing_key=signing_key), expected=status)
def bank_connection_requests_signed_request_new_node_identifier(bank): signing_key, _ = create_account() yield generate_signed_request(data={ 'ip_address': bank.ip_address, 'port': bank.port, 'protocol': bank.protocol, }, nid_signing_key=signing_key)
def confirmation_block_data(block_data, signing_key, confirmation_block_fake_data): yield generate_signed_request( data={ 'block': block_data, 'block_identifier': confirmation_block_fake_data['block_identifier'], 'updated_balances': [], }, nid_signing_key=signing_key )
def test_bank_account_number_trust(client, account, self_configuration, trust, response_msg): response = client.patch_json( reverse('account-detail', args=[account.account_number]), generate_signed_request(data={'trust': trust}, nid_signing_key=get_signing_key()), expected=HTTP_400_BAD_REQUEST, ) assert response['trust'] == [response_msg]
def test_banks_post(client, bank_fake_data, self_configuration): response = client.post_json(reverse('bank-list'), generate_signed_request( data=bank_fake_data, nid_signing_key=get_signing_key(), ), expected=status.HTTP_201_CREATED) bank_fake_data['trust'] = f'{bank_fake_data["trust"]:.2f}' assert response == bank_fake_data
def test_accounts_patch(client, account, account_fake_data, self_configuration): response = client.patch_json( reverse('account-detail', args=[account.account_number]), generate_signed_request(data=account_fake_data, nid_signing_key=get_signing_key()), expected=HTTP_200_OK, ) assert response['account_number'] != account_fake_data['account_number'] assert float(response['trust']) == account_fake_data['trust']
def invalid_block_data(block_data, signing_key, invalid_block_fake_data): yield generate_signed_request(data={ 'block': block_data, 'block_identifier': invalid_block_fake_data['block_identifier'], 'primary_validator_node_identifier': get_primary_validator().node_identifier, }, nid_signing_key=signing_key)
def test_banks_patch(client, bank, bank_fake_data, self_configuration): response = client.patch_json( reverse('bank-detail', args=[bank.node_identifier]), generate_signed_request( data=bank_fake_data, nid_signing_key=get_signing_key(), ), expected=status.HTTP_200_OK, ) assert response['trust'] == f'{bank_fake_data["trust"]:.2f}'
def test_crawl_start_200(client, primary_validator_configuration): client.post_json( reverse('crawl-list'), generate_signed_request( data={'crawl': CRAWL_COMMAND_START}, nid_signing_key=get_signing_key(), ), expected=HTTP_404_NOT_FOUND, ) assert cache.get(CRAWL_STATUS) is None
def primary_validator_updated(client, signing_key, validator, status): return client.post_json(reverse('primary_validator_updated-list'), generate_signed_request( data={ 'ip_address': validator.ip_address, 'port': validator.port, 'protocol': validator.protocol, }, nid_signing_key=signing_key), expected=status)
def test_validator_patch(client, primary_validator_configuration, validator, validator_fake_data): response = client.patch_json( reverse('validator-detail', args=[validator.node_identifier]), generate_signed_request( data=validator_fake_data, nid_signing_key=get_signing_key(), ), expected=HTTP_200_OK, ) assert float(response['trust']) == validator_fake_data['trust']
def test_banks_post(client, primary_validator_configuration, bank, bank_fake_data): response = client.post_json( reverse('bank-list'), generate_signed_request( data=bank_fake_data, nid_signing_key=get_signing_key(), ), expected=HTTP_200_OK, ) assert float(response['trust']) == bank_fake_data['trust']
def validator_connection_requests_signed_request_connect_to_itself( primary_validator_configuration): signing_key, _ = create_account() yield generate_signed_request(data={ 'ip_address': primary_validator_configuration.ip_address, 'port': primary_validator_configuration.port, 'protocol': primary_validator_configuration.protocol, }, nid_signing_key=signing_key)
def test_update_bank_with_invalid_trust_value(client, bank, self_configuration, trust, response_msg): response = client.patch_json( reverse('bank-detail', args=[bank.node_identifier]), generate_signed_request( data={'trust': trust}, nid_signing_key=get_signing_key(), ), expected=status.HTTP_400_BAD_REQUEST, ) assert response['trust'] == [response_msg]
def test_banks_post_400_connect_to_self(client, bank_connection_request_data, signing_key, self_configuration): bank_connection_request_data['ip_address'] = self_configuration.ip_address bank_connection_request_data['protocol'] = self_configuration.protocol response = client.post_json( reverse('connection_requests-list'), generate_signed_request( data=bank_connection_request_data, nid_signing_key=signing_key, ), expected=HTTP_400_BAD_REQUEST, ) assert response == {'non_field_errors': ['Unable to connect to self']}