def wait_for_confirmation(self, *args):
        if self.root.current == "WaitingForConfirmationScreen":
            self.my_socket.settimeout(0.1)
            username = self.params_for_wait_for_confirmation.username
            password = self.params_for_wait_for_confirmation.password
            private_key = self.params_for_wait_for_confirmation.key_private
            public_key = self.params_for_wait_for_confirmation.pk
            try:
                msg = MessageBetweenNodeAndClient()
                msg.recv(self.my_socket)
                if msg.message_type == MessageType.SIGN_UP_CONFIRMED:
                    # after the user has been processed{
                    pass  # TODO: add the new user to the db
                    self.wallet_database.add_new_user(username, password, private_key, public_key)
                    # TODO: log into into the user
                    # }
                    self.pressed_back()
                elif msg.message_type == MessageType.SIGN_UP_FAILED:
                    PopUp_Invalid_input('SIGN_UP_FAILED')
                    self.pressed_back()

            except socket.timeout:
                pass

            except ConnectionError:
                PopUp_Invalid_input('SIGN_UP_FAILED')
                self.pressed_back()
Exemple #2
0
 def send_block_upload_to_clients_if_needed(self, block: Block, reward_for_block: float):
     for username in list(self.dict_of_clients_and_usernames.keys()):
         if username == block.uploader_username:
             content = str(reward_for_block)
             msg = MessageBetweenNodeAndClient(MessageType.BLOCK_UPLOADED, content)
             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 receive_coins(self):

        # update gui {
        self.dict_of_repr_to_offered_transactions.pop(self.current_transaction.__str__())
        self.root.ids.ReceiveScreen.ids.OfferedTransactions.update_grid(
            self.dict_of_repr_to_offered_transactions.values(), self.move_to_receive_full_screen)
        # }
        my_signature = self.current_user.private_key.sign(self.current_transaction.data_as_str())
        self.current_transaction.receiver_signature = my_signature

        # send transaction with signature to server{
        msg_to_send = MessageBetweenNodeAndClient(MessageType.TRANSACTION_COMPLETED,
                                                  self.current_transaction.as_str())
        try:
            msg_to_send.send(self.my_socket)
            self.pressed_back()
        except ConnectionError:
            self.back_to_menu()
Exemple #5
0
    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 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 sign_up(self):
        username = self.root.ids.SignUpScreen.ids.username_wig.text
        password = self.root.ids.SignUpScreen.ids.password_wig.text
        self.root.ids.SignUpScreen.ids.username_wig.text = ""
        self.root.ids.SignUpScreen.ids.password_wig.text = ""
        if check_if_input_is_empty(username, password):
            PopUp_Invalid_input('fill out user and password')
        elif not check_username_validity(username):
            PopUp_Invalid_input('username must be only letters and numbers')
        else:
            while True:
                key_private = Key()
                pk = key_private.generate_public_key_and_private_key()

                # send sign up msg{
                list_of_data = [username, pk.as_str()]
                content = json.dumps(list_of_data)
                msg = MessageBetweenNodeAndClient(MessageType.SIGN_UP, content)
                try:
                    self.my_socket.settimeout(2)
                    msg.send(self.my_socket)

                    msg = MessageBetweenNodeAndClient()
                    msg.recv(self.my_socket)
                except ConnectionError as e:
                    PopUp_Invalid_input("server went offline")
                    self.pressed_back()
                    return

                    # }

                is_user_name_taken = bool(int(msg.content[0]))
                is_pk_taken = bool(int(msg.content[1]))
                if is_user_name_taken:
                    PopUp_Invalid_input('username is taken')
                    return
                elif is_pk_taken:
                    continue
                else:
                    break

            self.root.current = "WaitingForConfirmationScreen"
            self.params_for_wait_for_confirmation = ParamsWaitingForConfirmation(username, password, key_private, pk)
Exemple #8
0
    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 log_in(self):
        username = self.root.ids.LogInScreen.ids.username_wig.text
        password = self.root.ids.LogInScreen.ids.password_wig.text
        # username = '******'
        # password = '******'
        self.root.ids.LogInScreen.ids.username_wig.text = ""
        self.root.ids.LogInScreen.ids.password_wig.text = ""
        if check_if_input_is_empty(username, password):
            PopUp_Invalid_input('fill out user and password')
        elif not check_username_validity(username):
            PopUp_Invalid_input('username must be only letters and numbers')
        elif not self.wallet_database.is_user_exist(username):
            PopUp_Invalid_input(f'no user named {username}')
        elif not self.wallet_database.check_if_password_valid(username, password):
            PopUp_Invalid_input(f'wrong password')
        else:  # password and user correct
            current_username = username
            current_password = password
            current_pk, current_private_key = self.wallet_database.get_keys(username, password)
            self.current_user.set(current_username, current_password, current_private_key,
                                  current_pk)
            #  Send log in server with the user{
            try:
                self.my_socket.settimeout(7)

                msg = MessageBetweenNodeAndClient(MessageType.LOG_IN_REQUEST, username)
                msg.send(self.my_socket)

                msg = MessageBetweenNodeAndClient()

                msg.recv(self.my_socket)

                if msg.message_type == MessageType.LOG_IN_FAILED:
                    PopUp_Invalid_input('login failed')
                    self.current_user.clear()
                    self.pressed_back()
                    return
                elif msg.message_type != MessageType.LOG_IN_RAND:
                    raise Exception('unxpected msg')  # TODO

                signature = self.current_user.private_key.sign(msg.content)

                msg = MessageBetweenNodeAndClient(MessageType.LOG_IN_RAND_ANSWER, signature)
                msg.send(self.my_socket)

                msg = MessageBetweenNodeAndClient()
                msg.recv(self.my_socket)

                if msg.message_type == MessageType.LOG_IN_ACCEPTED:
                    self.root.current = "UserPageScreen"
                    self.root.ids.UserPageScreen.ids.username_label.text = self.current_user.username
                    # send to server GET_ALL_TRANSACTIONS{
                    msg_to_send = MessageBetweenNodeAndClient(MessageType.GET_ALL_TRANSACTIONS)
                    msg_to_send.send(self.my_socket)
                    self.my_socket.settimeout(Constants.SOCKET_CLIENT_RECEIVE_SHORT_TIMEOUT)
                    Clock.schedule_interval(self.recv_msg_from_server, 1)
                    # }
                elif msg.message_type == MessageType.LOG_IN_FAILED:
                    PopUp_Invalid_input('login failed')
                    self.pressed_back()
                else:
                    raise Exception('nfds')
            except ConnectionError:
                PopUp_Invalid_input(f'connection with server failed')
                self.pressed_back()
                print('471')
                return
            except socket.timeout:
                PopUp_Invalid_input(f'connection with server failed')
                self.pressed_back()
                print('471')
                return
    def process_block(self, block: Block, node):
        """
        this function will be called every time a block has passed the threshold to be considered secure
        then and only then the block content will be taken in to account

        when prosseisng a block you need to first of all him and then to add all of the ney users to the table
        in order to solve situations that the uploader is a new user
        :return:
        """

        if block.uploader_username == 'genesis':
            return

        if block.level % CHANGE_REWARD_FOR_BLOCK_FREQUENCY == 0:  # aka the time to half the reward has come
            self.general_val_table.half_reward_for_block()

            # add all new users{
        for user in block.list_of_new_users:
            self.users_table.add_user(user)
        # }

        # TODO: give reward to the block owner{
        if not self.users_table.is_user_exist(block.uploader_username):
            raise Exception(
                f'user that uploded block does not exist {block.uploader_username}\n{block.as_str()}'
            )
        current_balance = self.users_table.get_balance(block.uploader_username)
        self.users_table.update_balance(
            block.uploader_username, current_balance +
            self.general_val_table.get_current_reward_for_block())
        node.send_block_upload_to_clients_if_needed(
            block, self.general_val_table.get_current_reward_for_block())
        # }

        # TODO: handle all transactions {
        for transaction in block.list_of_transactions:
            if len(block.list_of_transactions) > 1:
                pass
            self.users_table.make_transaction(transaction, node)
            # node.send_transaction_to_clients_if_needed(transaction)
        # }

        list_of_transactions_as_str = [
            tran.as_str() for tran in block.list_of_transactions
        ]
        list_of_new_users_as_str = [
            user.as_str() for user in block.list_of_new_users
        ]

        if block.uploader_username == self.username:  # aka i am the one yo upload the block
            if not node.is_user_been_processed and node.user.as_str(
            ) in list_of_new_users_as_str:
                node.is_user_been_processed = True
            node.list_of_new_users_to_upload_waiting_to_be_processed = [
                user for user in
                node.list_of_new_users_to_upload_waiting_to_be_processed
                if user.as_str() not in list_of_new_users_as_str
            ]

            node.list_of_transactions_to_make_waiting_to_be_processed = [
                tran for tran in
                node.list_of_transactions_to_make_waiting_to_be_processed
                if tran.as_str() not in list_of_transactions_as_str
            ]
            for user in list(
                    node.dict_of_clients_and_usernames_waiting_for_confirmation
                    .keys()):
                if user.as_str() in list_of_new_users_as_str:
                    # send to the client that is waiting for confirmation that his user has been successfully uploaded{
                    client_socket = node.dict_of_clients_and_usernames_waiting_for_confirmation[
                        user]
                    msg = MessageBetweenNodeAndClient(
                        MessageType.SIGN_UP_CONFIRMED)
                    node.dict_of_clients_and_usernames_waiting_for_confirmation.pop(
                        user)  # remove
                    try:
                        msg.send(client_socket)
                    except ConnectionError:
                        pass
        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)