def send_transaction_to_clients_if_needed(self, transaction: Transaction): for username in list(self.dict_of_clients_and_usernames.keys()): if transaction.sender_username == username or transaction.receiver_username == username: if not self.server_database.users_table.is_user_exist( transaction.sender_username) or not self.server_database.users_table.is_user_exist( transaction.receiver_username): return # one of the users does not exist so so nothing sender = self.server_database.users_table.get_user(transaction.sender_username) receiver = self.server_database.users_table.get_user(transaction.receiver_username) if sender.balance - transaction.amount < 0: print('not enough money') return # aka not enough money if transaction.is_signature_valid(sender.pk, receiver.pk): # both valid msg = MessageBetweenNodeAndClient(MessageType.TRANSACTION_COMPLETED, transaction.as_str()) elif transaction.receiver_username == username and transaction.is_sender_signature_valid(sender.pk): msg = MessageBetweenNodeAndClient(MessageType.TRANSACTION_OFFERED, transaction.as_str()) else: continue try: msg.send(self.dict_of_clients_and_usernames[username]) except ConnectionError: self.dict_of_clients_and_usernames.pop(username)
def send_coins(self): """ called when user pressed send in the send coins screen :return: """ receiver_username = self.root.ids.SendScreen.ids.receiver_username_wig.text amount = self.root.ids.SendScreen.ids.amount_wig.text description = self.root.ids.SendScreen.ids.description_wig.text self.root.ids.SendScreen.ids.receiver_username_wig.text = '' self.root.ids.SendScreen.ids.amount_wig.text = '' self.root.ids.SendScreen.ids.description_wig.text = '' if check_if_input_is_empty(receiver_username, amount): PopUp_Invalid_input('fiil out username and amount ') return try: amount = float(amount) except ValueError: PopUp_Invalid_input('amount should be a a valid number') return if not amount > 0: PopUp_Invalid_input('amount should be positive') return if self.current_user.balance < amount: PopUp_Invalid_input('not enough money') return if self.current_user.username == receiver_username: PopUp_Invalid_input('cannot send money to yourself') return transaction = Transaction(self.current_user.username, receiver_username, amount, description) signature = self.current_user.private_key.sign(transaction.data_as_str()) transaction.sender_signature = signature try: msg = MessageBetweenNodeAndClient(MessageType.TRANSACTION_OFFERED, transaction.as_str()) msg.send(self.my_socket) except ConnectionError: self.back_to_menu() PopUp_Invalid_input('server dissconnected') return self.root.current = "UserPageScreen"
def add_declined_transaction(self, username: str, transaction: Transaction): lodt = self.get_list_of_declined_transactions(username) lodt.append(transaction.as_str()) lodt_as_str = json.dumps(lodt) command = f'''UPDATE Users SET LODT = '{lodt_as_str}' WHERE Username = '******';''' self.__cursor.execute(command) self.__connection.commit()
def process_transaction(self, transaction: Transaction, type: MessageType, change_balance=True): print(f'processing {transaction.as_str()}') print(f'reciver {transaction.receiver_username}') print(f'giver {transaction.sender_username}') if type == MessageType.TRANSACTION_COMPLETED: print('tran complete') if change_balance: self.update_balance(transaction=transaction) self.list_of_completed_transactions.append(transaction) if transaction.__str__() in self.dict_of_repr_to_offered_transactions.keys(): self.dict_of_repr_to_offered_transactions.pop(transaction.__str__()) self.root.ids.UserPageScreen.ids.RecantsTransactions.update_grid(self.list_of_completed_transactions) self.root.ids.ReceiveScreen.ids.OfferedTransactions.update_grid( self.dict_of_repr_to_offered_transactions.values(), self.move_to_receive_full_screen) elif type == MessageType.TRANSACTION_OFFERED: if transaction.as_str() in self.wallet_database.get_list_of_declined_transactions( self.current_user.username): return self.dict_of_repr_to_offered_transactions[transaction.__str__()] = transaction self.root.ids.ReceiveScreen.ids.OfferedTransactions.update_grid( self.dict_of_repr_to_offered_transactions.values(), self.move_to_receive_full_screen) else: raise Exception(f'unxepect msg {type.name}')
def recv_msg_from_server(self, *args): self.acquire() if self.root.current in ["UserPageScreen", "SendScreen", "FullReceiveScreen", "ReceiveScreen"]: # TODO add all needed screens try: msg = MessageBetweenNodeAndClient() msg.recv(self.my_socket) if msg.message_type == MessageType.RECEIVE_ALL_TRANSACTIONS: list_of_transactions, current_amount_of_money = json.loads(msg.content) print(float(current_amount_of_money), "current_amount_of_money") list_of_transactions = [ (Transaction.create_from_str(tup[0]), MessageType(int(tup[1]))) for tup in list_of_transactions] for tup in list_of_transactions: self.process_transaction(tup[0], tup[1], change_balance=False) # (transaction,msg_type) self.update_balance(amount=float(current_amount_of_money)) elif msg.message_type in [MessageType.TRANSACTION_OFFERED, MessageType.TRANSACTION_COMPLETED]: tran = Transaction.create_from_str(msg.content) self.process_transaction(tran, msg.message_type) Pop_notifications(Notification.create(msg.message_type), transaction_text=tran.__str__()) elif msg.message_type == MessageType.BLOCK_UPLOADED: amount = float(msg.content) self.update_balance(amount=amount) except socket.timeout: self.release() return except ConnectionError: PopUp_Invalid_input('server dissconected') self.root.current = "MenuScreen" self.close_socket() self.current_user.clear() self.release()
def create_block_from_tuple(tup: tuple): id, parent_id, sequence_number, level, security_number, uploader_username, last_block_hash, current_block_hash, proof_of_work, timestamp, list_of_transactions, list_of_new_users = tup list_of_new_users_as_str = json.loads(list_of_new_users) list_of_transactions_as_str = json.loads(list_of_transactions) list_of_new_users = [] list_of_transactions = [] for i in list_of_new_users_as_str: list_of_new_users.append(User.create_from_str(i)) for i in list_of_transactions_as_str: t = Transaction.create_from_str(i) list_of_transactions.append(t) b = Block(uploader_username, list_of_transactions, list_of_new_users, last_block_hash, timestamp, current_block_hash) b.set_table_parameters(id, parent_id, sequence_number, level, security_number) b.proof_of_work = proof_of_work return b
def create_block_from_tuple_received(tup): uploader_username, timestamp, list_of_transactions_as_str, list_of_new_users_as_str, pow, last_block_hash = tup list_of_new_users_as_str = json.loads(list_of_new_users_as_str) list_of_transactions_as_str = json.loads(list_of_transactions_as_str) list_of_new_users = [ User.create_from_str(user_as_str) for user_as_str in list_of_new_users_as_str ] list_of_transactions = [ Transaction.create_from_str(block_as_str) for block_as_str in list_of_transactions_as_str ] b = Block(uploader_username, list_of_transactions, list_of_new_users, last_block_hash, timestamp=timestamp) b.proof_of_work = pow return b
def get_all_transactions_of(self, username: str): if not self.users_table.is_user_exist(username): return [], -1 command = f'''SELECT LOT FROM Blockchain WHERE SecurityNumber > {self.blockchain_table.calculate_security_number_threshold()}''' list_to_send = [] self.blockchain_table.cursor.execute(command) list_of_list_of_transactions = self.blockchain_table.cursor.fetchall() for tup in list_of_list_of_transactions: list_of_transactions = json.loads(tup[0]) for transaction in list_of_transactions: transaction = Transaction.create_from_str(transaction) if transaction.sender_username == username or transaction.receiver_username == username: if not self.users_table.is_user_exist( transaction.sender_username ) or not self.users_table.is_user_exist( transaction.receiver_username): continue # one of the users does not exist so so nothing sender = self.users_table.get_user( transaction.sender_username) receiver = self.users_table.get_user( transaction.receiver_username) if transaction.is_signature_valid( sender.pk, receiver.pk): # both valid list_to_send.append(( transaction, MessageType.TRANSACTION_COMPLETED.value.__str__())) elif transaction.receiver_username == username and transaction.is_sender_signature_valid( sender.pk): list_to_send.append( (transaction, MessageType.TRANSACTION_OFFERED.value.__str__())) current_amount_of_money = float(self.users_table.get_balance(username)) return list_to_send, current_amount_of_money
def handle_client(self, client_socket: socket): username = '' client_socket.settimeout(0.2) client_state = ClientState.NOT_LOGGED_IN try: while True: try: self.acquire() if client_state == ClientState.NOT_LOGGED_IN: msg = MessageBetweenNodeAndClient() client_socket.settimeout(SOCKET_CLIENT_RECEIVE_SHORT_TIMEOUT) t = time.time() msg.recv(client_socket) client_socket.settimeout(SOCKET_CLIENT_RECEIVE_LONG_TIMEOUT) if msg.message_type == MessageType.SIGN_UP: list_of_data = json.loads(msg.content) username, pk_as_str = list_of_data pk = Key.create_from_str(pk_as_str) # check if pk and username are taken and send result to client { is_user_taken = self.server_database.users_table.is_user_exist(username) is_pk_taken = self.server_database.users_table.is_public_key_exist(pk) content = str(int(is_user_taken)) + str(int(is_pk_taken)) msg_to_send = MessageBetweenNodeAndClient(MessageType.SIGN_UP_ANSWER, content) msg_to_send.send(client_socket) # } if not is_user_taken and not is_pk_taken: pass # add user to upload user = User(username, pk) self.list_of_new_users_to_upload.append(user) self.dict_of_clients_and_usernames_waiting_for_confirmation[user] = client_socket client_state = ClientState.WAITING_FOR_CONFIRMATION else: pass elif msg.message_type == MessageType.LOG_IN_REQUEST: username = msg.content if not self.server_database.users_table.is_user_exist(username): print(f'not user named {username}') msg = MessageBetweenNodeAndClient(MessageType.LOG_IN_FAILED) msg.send(client_socket) random = str(randint(0, 10000)) msg = MessageBetweenNodeAndClient(MessageType.LOG_IN_RAND, random) msg.send(client_socket) msg.recv(client_socket) if msg.message_type != MessageType.LOG_IN_RAND_ANSWER: raise Exception('unxpexted msg') client_pk = self.server_database.users_table.get_public_key(username) if not client_pk.verify(msg.content, random): msg = MessageBetweenNodeAndClient(MessageType.LOG_IN_FAILED) else: msg = MessageBetweenNodeAndClient(MessageType.LOG_IN_ACCEPTED) msg.send(client_socket) client_socket.settimeout(SOCKET_CLIENT_RECEIVE_SHORT_TIMEOUT) self.dict_of_clients_and_usernames[username] = client_socket client_state = ClientState.LOGGED_IN else: raise Exception('unxpexted msg') elif client_state == ClientState.LOGGED_IN: msg = MessageBetweenNodeAndClient() msg.recv(client_socket) if msg.message_type == MessageType.GET_ALL_TRANSACTIONS: # serch the database for all transactions revolving the user { tuples, current_amount_of_money = self.server_database.get_all_transactions_of(username) print(f'current_amount_of_money {current_amount_of_money} (190)') content = json.dumps( [[(t[0].as_str(), t[1]) for t in tuples], str(current_amount_of_money)]) msg_to_send = MessageBetweenNodeAndClient( MessageType.RECEIVE_ALL_TRANSACTIONS, content) msg_to_send.send(client_socket) # } elif msg.message_type == MessageType.TRANSACTION_OFFERED: transaction = Transaction.create_from_str(msg.content) self.list_of_transactions_to_make.append(transaction) elif msg.message_type == MessageType.TRANSACTION_COMPLETED: transaction = Transaction.create_from_str(msg.content) self.list_of_transactions_to_make.append(transaction) elif client_state == ClientState.WAITING_FOR_CONFIRMATION: if self.dict_of_clients_and_usernames_waiting_for_confirmation.get(user) is None: client_socket.close() self.release() return self.release() except socket.timeout: self.release() except ConnectionError or json.decoder.JSONDecodeError as e: print(e) print('nlafsdfdsfdsfds') self.release() return
def make_transaction(self, transaction: Transaction, node): if not self.is_user_exist( transaction.receiver_username ) or not self.is_user_exist( transaction.sender_username ) or transaction.receiver_username == transaction.sender_username: return # one of the user does not exist or the receiver_username is also sender_username sender = self.get_user(transaction.sender_username) receiver = self.get_user(transaction.receiver_username) print( f'sender: {sender.username} , {sender.pk.as_str()}, {sender.balance}' ) print( f'receiver: {receiver.username} , {receiver.pk.as_str()}, {receiver.balance}' ) if sender.balance - transaction.amount < 0: print('not enough money') return # aka not enough money # TODO: check digital signature of both users{ sender_pk = sender.pk receiver_pk = receiver.pk is_tran_valid = transaction.is_signature_valid( sender_pk, receiver_pk) print(f'is_tran_valid {is_tran_valid}') # } # changing the users balance{ if is_tran_valid: self.update_balance(sender.username, sender.balance - transaction.amount) self.update_balance(receiver.username, receiver.balance + transaction.amount) for username in list(node.dict_of_clients_and_usernames.keys()): if transaction.sender_username == username or transaction.receiver_username == username: if not self.is_user_exist( transaction.sender_username ) or not self.is_user_exist(transaction.receiver_username): return # one of the users does not exist so so nothing if transaction.is_signature_valid( sender.pk, receiver.pk): # both valid msg = MessageBetweenNodeAndClient( MessageType.TRANSACTION_COMPLETED, transaction.as_str()) elif transaction.receiver_username == username and transaction.is_sender_signature_valid( sender.pk): print("transaction.receiver_signature", transaction.receiver_signature) msg = MessageBetweenNodeAndClient( MessageType.TRANSACTION_OFFERED, transaction.as_str()) else: continue try: msg.send(node.dict_of_clients_and_usernames[username]) except ConnectionError: node.dict_of_clients_and_usernames.pop(username)