def get_nodes(): """ Returns all peer nodes associated with blockchain """ all_nodes = blockchain.peer_nodes if all_nodes is None: return Response({'nodes': None}, get_message(HttpMethods.GET, False, 'node'), 500).get() return Response({'nodes': get_serializable_peer_nodes(blockchain.peer_nodes)}, get_message(HttpMethods.GET, True, 'node'), 200).get()
def get_balance(): if not blockchain.has_wallet: message = get_message(HttpMethods.GET, False, 'balance') return Response({'funds': 0, 'hasOwner': False}, message, 500).get() message = message = get_message(HttpMethods.GET, True, 'balance') return Response({'funds': blockchain.balance, 'hasOwner': True}, message, 200).get()
def test_serialize_200_ok_response_with_html_body(): body = b'<h1>jee</h1>\r\n' content_type = 'Content-Type: text/html' content_length = f'Content-Length: {len(body)}' headers = [content_type, content_length] response = Response(200, headers, body) expected_result = b'HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: 14\r\n\r\n<h1>jee</h1>\r\n' assert response.serialize() == expected_result
def load_wallet(): blockchain.load_wallet() if blockchain.has_wallet: message = get_message(HttpMethods.GET, True, 'wallet') return Response({'public_key': blockchain.owner, 'savedWallet': True}, message, 200).get() message = get_message(HttpMethods.GET, False, 'wallet') return Response({'public_key': blockchain.owner, 'savedWallet': False}, message, 500).get()
def get_open_transactions(): if not blockchain.has_wallet: message = get_message(HttpMethods.GET, False, 'open transaction', additional_info='No Wallet found!') return Response({'open_transactions': None}, message, 500).get() message = get_message(HttpMethods.GET, True, 'open transaction', ) return Response({'open_transactions': get_serializable_transaction(blockchain.open_transactions)}, message, 200).get()
def create_node(): """ Adds a node to the blockchain peer nodes """ body: Dict = request.get_json() node_to_add = body.get('node') if not body or not node_to_add: return Response({'nodes': get_serializable_peer_nodes(blockchain.peer_nodes)}, get_message(HttpMethods.POST, False, 'node', additional_info='Please provide a valid node to add.'), 400).get() if blockchain.add_peer_node(node_to_add): return Response({'node': get_serializable_peer_nodes(blockchain.peer_nodes)}, get_message(HttpMethods.POST, True, 'node'), 200).get() return Response({'nodes': get_serializable_peer_nodes(blockchain.peer_nodes)}, get_message(HttpMethods.POST, False, 'node', additional_info=f'Saving peer node {node_to_add} failed!'), 400).get()
def delete_node(peer_node: str): """ Deletes a node from the blockchain peer nodes """ node_to_delete = peer_node if not len(node_to_delete): return Response({'nodes': get_serializable_peer_nodes(blockchain.peer_nodes)}, get_message(HttpMethods.DELETE, False, 'node', additional_info='Please provide a valid node to delete.'), 400).get() if not node_to_delete in blockchain.peer_nodes: return Response({'node': get_serializable_peer_nodes(blockchain.peer_nodes)}, get_message(HttpMethods.DELETE, False, 'node', additional_info=f'Delete peer node {node_to_delete} failed. No peer node found!'), 500).get() blockchain.remove_peer_node(node_to_delete) return Response({'nodes': get_serializable_peer_nodes(blockchain.peer_nodes)}, get_message(HttpMethods.DELETE, True, 'node'), 200).get()
def ensure_wallet(blockchain: Blockchain, *, action_subject: str) -> Union[None, Response]: """ Handles Response for Requests with missing wallet """ if not blockchain.has_wallet: message = get_message(HttpMethods.POST, False, action_subject, additional_info='No Wallet found!') return Response({action_subject: None}, message, 500).get()
def ensure_tx_appended(add_transaction_success: bool) -> Union[None, Response]: if not add_transaction_success: message = get_message(HttpMethods.POST, False, 'transaction') return Response( { 'transaction': None, 'missing_fields': None, "transactions_synced": False }, message, 500).get()
def resolve_conflicts(): blockchain_replaced = blockchain.resolve_conflicts() if blockchain_replaced: blockchain.has_conflicts = False conflict_message = 'Conflict succesfully resolved.' if blockchain_replaced else 'No Conflict found. Blockchain unchanged.' message = get_message(HttpMethods.POST, blockchain_replaced, 'conflict', additional_info=conflict_message) return Response({'conflictResolved': blockchain_replaced}, message, HttpStatusCodes.SUCCESS).get()
def mine(): if blockchain.has_conflicts: message = get_message(HttpMethods.POST, False, 'block', additional_info='Conflict: Please resolve the conflict first!') return Response({'blockSynced': False, 'conflict': True}, message, HttpStatusCodes.CONFLICT).get() try: mining_successful = blockchain.mine() created_block = blockchain.latest_block if mining_successful and created_block: blockSyncer = BlockSync(blockchain.peer_nodes) broadcast_tx_succes, has_conflicts = blockSyncer.broadcast( created_block) blockchain.has_conflicts = has_conflicts return Response({'block': get_serializable_block(created_block), 'blockSynced': broadcast_tx_succes, 'conflict': blockchain.has_conflicts}, get_message(HttpMethods.POST, True, 'block'), HttpStatusCodes.SUCCESS).get() if mining_successful else Response({'error': True}, get_message(HttpMethods.POST, False, 'block'), 400).get() except Exception as error: message = get_message(HttpMethods.POST, False, 'block', additional_info=f'(Error: {error})') return Response({'blockSynced': False}, message, HttpStatusCodes.SERVER_ERROR).get()
def broadcast_transactions(): transaction_data: Union(Dict, None) = request.get_json() ensure_required_fields(transaction_data, RequiredFields.get_required_fields(BlockchainEndpoints.TRANSACTION), action_subject='broadcast transaction') ensure_tx_appended(blockchain.add_transaction( **transaction_data, is_broadcast_tx=True)) message = get_message(HttpMethods.POST, True, 'broadcast transaction') return Response({'transaction': get_serializable_transaction(blockchain.latest_transaction), 'missing_fields': None, "transactions_synced": True}, message, 200).get()
def broadcast_block(): block_data: Union(Dict, None) = request.get_json() ensure_required_fields(block_data, RequiredFields.get_required_fields(BlockchainEndpoints.BROADCAST_BLOCK), action_subject='broadcast block') broadcast_block = block_from_deserialized_block(block_data['block']) successMessage = get_message(HttpMethods.POST, True, 'broadcast block') errorMessage = get_message(HttpMethods.POST, False, 'broadcast block') if is_next_block(blockchain, broadcast_block): blockchain_added = blockchain.add_block(broadcast_block) if blockchain_added: return Response({}, successMessage, 200).get() return Response({}, errorMessage, 400).get() elif is_future_block(blockchain, broadcast_block): blockchain.has_conflicts = True return Response({}, errorMessage, 200).get() elif is_previous_block(blockchain, broadcast_block): return Response({}, errorMessage, HttpStatusCodes.CONFLICT).get()
def add_transaction(): ensure_wallet(blockchain, action_subject='transaction') transaction_data: Union(Dict, None) = request.get_json() ensure_required_fields(transaction_data, RequiredFields.get_required_fields(BlockchainEndpoints.TRANSACTION), action_subject='transaction') ensure_tx_appended(blockchain.add_transaction(**transaction_data)) tx_syncer = TransactionSync(blockchain.peer_nodes) broadcast_tx_succes, _ = tx_syncer.broadcast( blockchain.latest_transaction) message = get_message(HttpMethods.POST, True, 'transaction') return Response({'transaction': get_serializable_transaction(blockchain.latest_transaction), 'missing_fields': None, "transactions_synced": broadcast_tx_succes}, message, 200).get()
def ensure_required_fields(data: Union[Dict, None], required_fields: List[str], *, action_subject: str) -> Union[None, Response]: """ Handles Response for Requests with missing fields """ if not has_all_required_fields(data, required_fields): missing_fields = get_missing_fields(data, required_fields) missing_fields_stringified = ', '.join(missing_fields) message = get_message( HttpMethods.POST, False, action_subject, additional_info= f'Please Provide complete {action_subject}. Missing Fields: {missing_fields_stringified}' ) return Response( { action_subject: None, 'missing_fields': missing_fields, "transactions_synced": False }, message, 400).get()
def create_wallet(): saved = False error = False try: _, private_key = blockchain.create_wallet() except: error = True should_save = get_param(request, 'save') if(should_save and not error): try: saved = blockchain.save_wallet() except: error = True success = error is False message = get_message(HttpMethods.POST, success, 'wallet') status = 201 if success else 500 return Response({'public_key': blockchain.owner, 'private_key': private_key, 'savedWallet': saved}, message, status).get()
def test_serialize_204_no_content_response_without_headers_and_body(): response = Response(204) expected_result = b'HTTP/1.1 204 No Content\r\n\r\n' assert response.serialize() == expected_result
def test_serialize_200_ok_response_without_headers_and_body(): response = Response(200) expected_result = b'HTTP/1.1 200 OK\r\n\r\n' assert response.serialize() == expected_result