Пример #1
0
    def send_funds_from_to(self, sender_public_key_str: str, sender_private_key_str: str,
                           recipient_public_key_str: str, value: float):
        if self.get_balance_for_public_key(sender_public_key_str) < value:
            print("Not enough balance, transaction discarded")
            return None

        if value <= 0:
            print("Value should be positive, transaction discarded")
            return None

        inputs = []
        total = 0
        for transaction_id, utxo in self.all_utxos.items():
            if utxo.is_mine(sender_public_key_str):
                total += utxo.value
                inp = TransactionInput(transaction_id)
                inputs.append(inp)

                if total >= value + self.fee:
                    break

        transaction = Transaction(sender_public_key_str, recipient_public_key_str, value, inputs)
        encoded = base64.b64decode(sender_private_key_str.encode('utf8'))
        sender_private_formated = PEM.encode(encoded, 'RSA PRIVATE KEY')
        transaction.generate_signature(import_key(sender_private_formated.encode('utf8')))
        transaction.process_transaction(self.all_utxos, self.minimum_transaction, self.fee)
        return transaction
Пример #2
0
    def generate(self):
        inputs = \
            [
                TransactionInput(
                    src_hash=int_to_bytes(
                        random.randint(0, sys.maxsize)),
                    src_idx=random.randint(
                        0, constants.TRANSACTION_MAX_OUTPUTS),
                    signature=int_to_bytes(
                        random.randint(0, sys.maxsize)),
                    key=self._ecdsa.public_key
                )
                for _ in range(constants.TRANSACTION_MAX_INPUTS)
            ]

        outputs = \
            [
                TransactionOutput(
                    amount=random.randint(0, 1000),
                    key=int_to_bytes(random.randint(0, sys.maxsize)),
                )
                for _ in range(constants.TRANSACTION_MAX_OUTPUTS)
            ]

        return Transaction(inputs=inputs, outputs=outputs)
Пример #3
0
    def send_funds(self, all_utxos, recipient_public_key_str: str,
                   value: float) -> Transaction:
        self.update_utxos(all_utxos)

        if self.get_balance(all_utxos) < value:
            raise Exception("Not enough balance, transaction discarded")

        if value <= 0:
            raise Exception("Value should be positive, transaction discarded")

        inputs = []
        total = 0
        for transaction_id, utxo in self.utxos.items():
            total += utxo.value
            inp = TransactionInput(transaction_id)
            inputs.append(inp)

            if total >= value:
                break

        transaction = Transaction(self.public_key_str,
                                  recipient_public_key_str, value, inputs)
        transaction.generate_signature(self.private_key)

        for inp in inputs:
            del self.utxos[inp.transaction_output_id]

        return transaction
Пример #4
0
    def generate(self):
        console.info("generating a transaction")

        tx, src_idx, amount_available = self.find_unspent()

        src_hash = tx.hash
        message = src_hash + int_to_bytes(src_idx)
        signature = self._ecdsa.sign(message)
        key = self._ecdsa.public_key

        tx_input = TransactionInput(
            src_hash=src_hash,
            src_idx=src_idx,
            signature=signature,
            key=key
        )

        amount_send = int(amount_available * random.random())
        fee = int((amount_available - amount_send) * random.random())
        amount_rest = amount_available - amount_send - fee

        peers_with_address = self.peers_with_address()

        # If no known peers, we will send to ourselves
        receiver_key = self._ecdsa.public_key

        # Choose coin receiver at random
        try:
            receiver = random.choice(peers_with_address)
            receiver_key = receiver.address
        except IndexError:
            pass

        # Output that transfers `amount_send` coins to the chosen node
        output_send = TransactionOutput(
            amount=amount_send,
            key=receiver_key
        )

        # Output that transfers the rest of the coins back to us.
        # The coins that are not in outputs constitute the transaction fee
        # (will be collected by the miner who will incude this transaction into
        # a new block)
        output_rest = TransactionOutput(
            amount=amount_rest,
            key=self._ecdsa.public_key
        )

        return Transaction(
            inputs=[tx_input],
            outputs=[output_send, output_rest]
        )
Пример #5
0
    def deserialize(cls, info: dict):
        sender = info['sender_public_key']
        receiver = info['receiver_public_key']
        value = info['value']

        inputs = []
        for input_data in info['input']:
            inputs.append(TransactionInput.deserialize(input_data))

        outputs = []
        for output_data in info['output']:
            outputs.append(TransactionOutput.deserialize(output_data))

        transaction = Transaction(sender, receiver, value, inputs)
        transaction.transaction_id = info['id']
        transaction.signature = info['signature']
        transaction.outputs = outputs

        return transaction
Пример #6
0
    def create_gift_coin(self, blockchain):
        """
        This method creates a new coin for the new client
        """
        # Get address of the client
        hash_public_key = self.hash_pubkey()

        coin_gift_tx_input = TransactionInput(prev_tx="1" * 64,
                                              pk_spender="1" * 64,
                                              signature=bytes(
                                                  "\x11" * 64,
                                                  encoding="utf-8"))
        coin_gift_tx_output = TransactionOutput(
            value=100, hash_pubkey_recipient=hash_public_key)
        coin_gift_tx = Transaction(tx_input=coin_gift_tx_input,
                                   tx_output=coin_gift_tx_output)

        transactions = [coin_gift_tx]

        nonce = 0
        new_block = None
        while True:
            if len(blockchain.blocks) != 0:
                hash_prev_block = blockchain.blocks[len(blockchain.blocks) -
                                                    1].get_hash()
                new_block = Block(transactions, nonce, hash_prev_block)
            else:
                new_block = Block(transactions=transactions,
                                  nonce=nonce,
                                  prev_block_hash="0" * 64)

            if new_block.get_hash().startswith("0" * blockchain.difficulty):
                print("Nonce found:", nonce)
                break

            nonce += 1

        print(coin_gift_tx.serialize())
        message = "\x12" + new_block.serialize()
        self.socket.sendall(message.encode('utf-8'))
Пример #7
0
    def send_message(self):
        while True:
            input_command = input()

            # This variable is set to True when is a server command
            send_message_to_server = True

            if input_command.startswith("cmd_new_tx"):

                # Show available transactions
                block_number = 0
                print("==> List of available transactions:")
                print(self.blockchain.blocks)
                tx_unspent_counter = 0
                for block in self.blockchain.blocks:
                    transaction_number = 0
                    for transaction in block.transactions:
                        if transaction.tx_output.hash_pubkey_recipient == self.hash_pubkey() and \
                                not transaction.is_already_spent(self.blockchain):
                            tx_unspent_counter += 1
                            print("\t -- [ B:", block_number, " - T:",
                                  transaction_number, "]", "Value:",
                                  transaction.tx_output.value)
                        transaction_number += 1
                    block_number += 1

                if tx_unspent_counter > 0:
                    block_number_spend = int(input("\tSelect block number: "))
                    transaction_number_spend = int(
                        input("\tSelect transaction number: "))

                    transaction_spend = self.blockchain.blocks[
                        block_number_spend].transactions[
                            transaction_number_spend]
                    address = input("\tAddress: ")
                    value = int(input("\tValue: "))

                    signature_information = transaction_spend.get_hash() + \
                        transaction_spend.tx_output.hash_pubkey_recipient + \
                        address + \
                        str(value)

                    route_private_key = "private_keys/" + str(
                        self.socket.getsockname()[1]) + "_private_key.pem"
                    hash_message = SHA256.new(
                        signature_information.encode("utf-8"))
                    private_key = ECC.import_key(
                        open(route_private_key).read())
                    signer = DSS.new(private_key, "fips-186-3")
                    signature = signer.sign(hash_message)

                    new_tx_input = TransactionInput(
                        prev_tx=transaction_spend.get_hash(),
                        signature=signature,
                        pk_spender=self.load_public_key())
                    new_tx_output = TransactionOutput(
                        value=value, hash_pubkey_recipient=address)

                    new_transaction = Transaction(tx_input=new_tx_input,
                                                  tx_output=new_tx_output)
                    print("\t-- Signing and sending transaction.")
                    message = "\x10" + new_transaction.serialize()
                else:
                    print("\t-- You do not have unspent transactions")
                    send_message_to_server = False

            elif input_command.startswith("cmd_show_addresses"):
                # This is not a server command
                send_message_to_server = False

                base_path = "public_keys/"
                for file in os.listdir(base_path):
                    pubkey_file = open(base_path + file)
                    pubkey = pubkey_file.read()

                    hash_object = RIPEMD160.new(data=pubkey.encode("utf-8"))
                    print("\t>>", hash_object.hexdigest(), "[", file, "]")

                    pubkey_file.close()

            elif input_command.startswith("cmd_gift"):
                send_message_to_server = False
                self.create_gift_coin(self.blockchain)
            else:
                message = input_command

            if send_message_to_server:
                self.socket.sendall(message.encode('utf-8'))