コード例 #1
0
    def test_verify_transaction(self):
        tx_input = Spendable(200, '18eKkAWyU9kvRNHPKxnZb6wwtPMrNmRRRA',
                             h2b('8443b07464c762d7fb404ea918a5ac9b3618d5cd6a0c5ea6e4dd5d7bbe28b154'), 0)
        tx_outs = [tx_utils.create_transaction_output('mgAqW5ZCnEp7fjvpj8RUL3WxsBy8rcDcCi', 0.0000275)]
        op_return_val = h2b('e9cee71ab932fde863338d08be4de9dfe39ea049bdafb342ce659ec5450b69ae')
        tx = tx_utils.create_trx(op_return_val, 3, 'mgAqW5ZCnEp7fjvpj8RUL3WxsBy8rcDcCi', tx_outs, tx_input)

        hextx = hexlify(tx.serialize())

        tx_utils.verify_transaction(hextx, hexlify(op_return_val))
コード例 #2
0
    def test_verify_transaction(self):
        cost = TransactionCosts(0.0001, 0.0000275, 3)
        tx_input = Spendable(200, '18eKkAWyU9kvRNHPKxnZb6wwtPMrNmRRRA',
                             h2b('8443b07464c762d7fb404ea918a5ac9b3618d5cd6a0c5ea6e4dd5d7bbe28b154'), 0)
        tx_outs = [trx_utils.create_transaction_output('mgAqW5ZCnEp7fjvpj8RUL3WxsBy8rcDcCi', 0.0000275)]
        op_return_val = h2b('e9cee71ab932fde863338d08be4de9dfe39ea049bdafb342ce659ec5450b69ae')
        tx = trx_utils.create_trx(op_return_val, cost, 'mgAqW5ZCnEp7fjvpj8RUL3WxsBy8rcDcCi', tx_outs, tx_input)

        hextx = hexlify(tx.serialize())

        trx_utils.verify_transaction(hextx, hexlify(op_return_val))
コード例 #3
0
    def issue_on_blockchain(self, wallet, revocation_address, split_input_trxs,
                            allowable_wif_prefixes, broadcast_function,
                            issuing_transaction_cost):

        trxs = self.create_transactions(wallet, revocation_address,
                                        issuing_transaction_cost,
                                        split_input_trxs)
        for td in trxs:
            # persist tx
            hextx = hexlify(td.tx.serialize())
            with open(td.unsigned_tx_file_name, 'w') as out_file:
                out_file.write(hextx)

            # sign transaction and persist result
            signed_hextx = trx_utils.sign_tx(hextx, td.tx_input,
                                             allowable_wif_prefixes)
            with open(td.signed_tx_file_name, 'w') as out_file:
                out_file.write(signed_hextx)

            # verify
            cert_utils.verify_transaction(td.op_return_value, signed_hextx)

            # send tx and persist txid
            txid = trx_utils.send_tx(broadcast_function, signed_hextx)
            self.finish_tx(td.sent_tx_file_name, txid)
コード例 #4
0
    def create_transactions(self, wallet, revocation_address,
                            issuing_transaction_cost, split_input_trxs):
        # finish tree
        self.tree.make_tree()

        op_return_value = unhexlify(self.tree.get_merkle_root())

        unspent_outputs = wallet.get_unspent_outputs(self.issuing_address)
        last_output = unspent_outputs[-1]

        txouts = self.build_txouts(issuing_transaction_cost)
        txouts = txouts + [
            trx_utils.create_transaction_output(
                revocation_address, issuing_transaction_cost.min_per_output)
        ]

        tx = trx_utils.create_trx(op_return_value, issuing_transaction_cost,
                                  self.issuing_address, txouts, last_output)

        unsigned_tx_file_name = convert_file_name(
            self.config.unsigned_txs_file_pattern, self.batch_id)
        unsent_tx_file_name = convert_file_name(
            self.config.signed_txs_file_pattern, self.batch_id)
        sent_tx_file_name = convert_file_name(
            self.config.sent_txs_file_pattern, self.batch_id)

        td = TransactionData(uid=self.batch_id,
                             tx=tx,
                             tx_input=last_output,
                             op_return_value=hexlify(op_return_value),
                             unsigned_tx_file_name=unsigned_tx_file_name,
                             signed_tx_file_name=unsent_tx_file_name,
                             sent_tx_file_name=sent_tx_file_name)

        return [td]
コード例 #5
0
 def test_create_trx(self):
     tx_input = Spendable(200, '18eKkAWyU9kvRNHPKxnZb6wwtPMrNmRRRA',
                          h2b('8443b07464c762d7fb404ea918a5ac9b3618d5cd6a0c5ea6e4dd5d7bbe28b154'), 0)
     tx_outs = [tx_utils.create_transaction_output('mgAqW5ZCnEp7fjvpj8RUL3WxsBy8rcDcCi', 0.0000275)]
     tx = tx_utils.create_trx('TEST'.encode('utf-8'), 3, 'mgAqW5ZCnEp7fjvpj8RUL3WxsBy8rcDcCi', tx_outs, tx_input)
     hextx = hexlify(tx.serialize())
     self.assertEquals(hextx,
                       '01000000018443b07464c762d7fb404ea918a5ac9b3618d5cd6a0c5ea6e4dd5d7bbe28b1540000000000ffffffff0300000000000000001976a914072a22e5913cd939904c46bbd0bc56755543384b88acc5000000000000001976a914072a22e5913cd939904c46bbd0bc56755543384b88ac0000000000000000066a045445535400000000')
コード例 #6
0
    def issue_on_blockchain(self):
        """
        Issue the certificates on the Bitcoin blockchain
        :param revocation_address:
        :return:
        """

        self.tree.make_tree()
        op_return_value_bytes = unhexlify(self.tree.get_merkle_root())
        op_return_value = hexlify(op_return_value_bytes)
        spendables = self.connector.get_unspent_outputs(self.issuing_address)
        if not spendables:
            error_message = 'No money to spend at address {}'.format(self.issuing_address)
            logging.error(error_message)
            raise InsufficientFundsError(error_message)

        last_input = spendables[-1]

        tx = self.transaction_handler.create_transaction(last_input, op_return_value_bytes)

        hex_tx = hexlify(tx.serialize())
        logging.info('Unsigned hextx=%s', hex_tx)

        prepared_tx = tx_utils.prepare_tx_for_signing(hex_tx, [last_input])
        with FinalizableSigner(self.secure_signer) as signer:
            signed_tx = signer.sign_transaction(prepared_tx)

        # log the actual byte count
        tx_byte_count = tx_utils.get_byte_count(signed_tx)
        logging.info('The actual transaction size is %d bytes', tx_byte_count)

        signed_hextx = signed_tx.as_hex()
        logging.info('Signed hextx=%s', signed_hextx)

        # verify transaction before broadcasting
        tx_utils.verify_transaction(signed_hextx, op_return_value)

        # send tx and persist txid
        tx_id = self.connector.broadcast_tx(signed_tx)
        if tx_id:
            logging.info('Broadcast transaction with txid %s', tx_id)
        else:
            logging.warning(
                'could not broadcast transaction but you can manually do it! signed hextx=%s', signed_hextx)

        return tx_id
コード例 #7
0
 def test_bitcoind_connector_spendables(self):
     bc = BitcoindConnector('XTN')
     spendables = bc.spendables_for_address('mz7poFND7hVGRtPWjiZizcCnjf6wEDWjjT')
     self.assertEquals(len(spendables), 3)
     self.assertEquals(hexlify(spendables[0].tx_hash),
                       '08f6528ac70c828e1633babc8f0d49ecb11649fd7451f76923821a0dbc81eb34')
     self.assertEquals(spendables[0].coin_value, 49000000)
     self.assertEquals(spendables[1].coin_value, 2750)
     self.assertEquals(spendables[2].coin_value, 2750)
コード例 #8
0
 def test_create_trx(self):
     cost = TransactionCosts(0.0001, 0.0000275, 3)
     tx_input = Spendable(200, '18eKkAWyU9kvRNHPKxnZb6wwtPMrNmRRRA',
                          h2b('8443b07464c762d7fb404ea918a5ac9b3618d5cd6a0c5ea6e4dd5d7bbe28b154'), 0)
     tx_outs = [trx_utils.create_transaction_output('mgAqW5ZCnEp7fjvpj8RUL3WxsBy8rcDcCi', 0.0000275)]
     tx = trx_utils.create_trx('TEST'.encode('utf-8'), cost, 'mgAqW5ZCnEp7fjvpj8RUL3WxsBy8rcDcCi', tx_outs, tx_input)
     hextx = hexlify(tx.serialize())
     self.assertEquals(hextx,
                       '01000000018443b07464c762d7fb404ea918a5ac9b3618d5cd6a0c5ea6e4dd5d7bbe28b1540000000000ffffffff0300000000000000001976a914072a22e5913cd939904c46bbd0bc56755543384b88acc5000000000000001976a914072a22e5913cd939904c46bbd0bc56755543384b88ac0000000000000000066a045445535400000000')
コード例 #9
0
 def test_bitcoind_connector_spendables(self):
     bitcoin.SelectParams('testnet')
     bc = BitcoindConnector('XTN')
     spendables = bc.spendables_for_address('mz7poFND7hVGRtPWjiZizcCnjf6wEDWjjT')
     self.assertEquals(len(spendables), 3)
     self.assertEquals(hexlify(spendables[0].tx_hash),
                       '08f6528ac70c828e1633babc8f0d49ecb11649fd7451f76923821a0dbc81eb34')
     self.assertEquals(spendables[0].coin_value, 49000000)
     self.assertEquals(spendables[1].coin_value, 2750)
     self.assertEquals(spendables[2].coin_value, 2750)
コード例 #10
0
    def create_transactions(self, revocation_address,
                            issuing_transaction_cost):
        """
        Create the batch Bitcoin transaction
        :param revocation_address:
        :param issuing_transaction_cost:
        :return:
        """
        self.tree.make_tree()

        spendables = get_unspent_outputs(self.issuing_address)
        if not spendables:
            error_message = 'No money to spend at address {}'.format(
                self.issuing_address)
            logging.error(error_message)
            raise InsufficientFundsError(error_message)

        last_input = spendables[-1]

        op_return_value = unhexlify(self.tree.get_merkle_root())

        tx_outs = self.build_recipient_tx_outs()
        tx_outs.append(
            trx_utils.create_transaction_output(
                revocation_address, issuing_transaction_cost.min_per_output))

        transaction = trx_utils.create_trx(op_return_value,
                                           issuing_transaction_cost,
                                           self.issuing_address, tx_outs,
                                           last_input)

        unsigned_tx_file_name = convert_file_name(
            self.config.unsigned_txs_file_pattern, self.batch_id)
        unsent_tx_file_name = convert_file_name(
            self.config.signed_txs_file_pattern, self.batch_id)
        sent_tx_file_name = convert_file_name(
            self.config.sent_txs_file_pattern, self.batch_id)

        transaction_data = TransactionData(
            uid=self.batch_id,
            tx=transaction,
            tx_input=last_input,
            op_return_value=hexlify(op_return_value),
            unsigned_tx_file_name=unsigned_tx_file_name,
            signed_tx_file_name=unsent_tx_file_name,
            sent_tx_file_name=sent_tx_file_name)

        return [transaction_data]
コード例 #11
0
    def issue_on_blockchain(self, revocation_address,
                            issuing_transaction_cost):
        """
        Issue the certificates on the Bitcoin blockchain
        :param revocation_address:
        :param issuing_transaction_cost:
        :return:
        """
        transactions_data = self.create_transactions(revocation_address,
                                                     issuing_transaction_cost)
        for transaction_data in transactions_data:
            unsigned_tx_file_name = transaction_data.batch_metadata.unsigned_tx_file_name
            signed_tx_file_name = transaction_data.batch_metadata.unsent_tx_file_name
            sent_tx_file_name = transaction_data.batch_metadata.sent_tx_file_name

            # persist the transaction in case broadcasting fails
            hex_tx = hexlify(transaction_data.tx.serialize())
            with open(unsigned_tx_file_name, 'w') as out_file:
                out_file.write(hex_tx)

            # sign transaction and persist result
            signed_tx = self.signer.sign_tx(hex_tx, transaction_data.tx_input,
                                            self.netcode)

            # log the actual byte count
            tx_byte_count = trx_utils.get_byte_count(signed_tx)
            logging.info('The actual transaction size is %d bytes',
                         tx_byte_count)

            signed_hextx = signed_tx.as_hex()
            with open(signed_tx_file_name, 'w') as out_file:
                out_file.write(signed_hextx)

            # verify transaction before broadcasting
            trx_utils.verify_transaction(signed_hextx,
                                         transaction_data.op_return_value)

            # send tx and persist txid
            tx_id = self.connector.broadcast_tx(signed_tx)
            if tx_id:
                logging.info('Broadcast transaction with txid %s', tx_id)
            else:
                logging.warning(
                    'could not broadcast transaction but you can manually do it! signed hextx=%s',
                    signed_hextx)

            self.persist_tx(sent_tx_file_name, tx_id)
コード例 #12
0
def _build_certificate_transactions(wallet, issuing_address,
                                    revocation_address, certificate_metadata,
                                    fees, tail):
    """Make transactions for the certificates.
    """
    logging.info('Creating tx of certificate for recipient uid: %s ...',
                 certificate_metadata.uid)

    with open(certificate_metadata.certificate_hash_file_name,
              'rb') as in_file:
        # this is the recipient-specific hash that will be recorded on the
        # blockchain
        hashed_certificate = in_file.read()
        cert_out = CMutableTxOut(0, CScript([OP_RETURN, hashed_certificate]))

        # send a transaction to the recipient's public key, and to a revocation
        # address
        txouts = create_recipient_outputs(certificate_metadata.pubkey,
                                          revocation_address,
                                          fees.min_per_output)

        # define transaction inputs
        unspent_outputs = wallet.get_unspent_outputs(issuing_address)
        last_input = unspent_outputs[tail]

        txins = [CTxIn(last_input.outpoint)]
        value_in = last_input.amount

        # very important! If we don't send the excess change back to ourselves,
        # some lucky miner gets it!
        amount = value_in - fees.cost_per_transaction
        if amount > 0:
            change_out = create_transaction_output(issuing_address, amount)
            txouts = txouts + [change_out]

        txouts = txouts + [cert_out]
        tx = CMutableTransaction(txins, txouts)

        # this is the transaction for a recipient, unsigned
        hextx = hexlify(tx.serialize())
        with open(certificate_metadata.unsigned_tx_file_name,
                  'wb') as out_file:
            out_file.write(bytes(hextx, 'utf-8'))

        logging.info('Created unsigned tx for recipient; last_input=%s',
                     last_input)
        return last_input
コード例 #13
0
def _build_certificate_transactions(wallet, issuing_address, revocation_address, certificate_metadata, fees, tail):
    """Make transactions for the certificates.
    """
    logging.info('Creating tx of certificate for recipient uid: %s ...',
                 certificate_metadata.uid)

    with open(certificate_metadata.certificate_hash_file_name, 'rb') as in_file:
        # this is the recipient-specific hash that will be recorded on the
        # blockchain
        hashed_certificate = in_file.read()
        cert_out = CMutableTxOut(0, CScript([OP_RETURN, hashed_certificate]))

        # send a transaction to the recipient's public key, and to a revocation
        # address
        txouts = create_recipient_outputs(
            certificate_metadata.pubkey, revocation_address, fees.min_per_output)

        # define transaction inputs
        unspent_outputs = wallet.get_unspent_outputs(issuing_address)
        last_input = unspent_outputs[tail]

        txins = [CTxIn(last_input.outpoint)]
        value_in = last_input.amount

        # very important! If we don't send the excess change back to ourselves,
        # some lucky miner gets it!
        amount = value_in - fees.cost_per_transaction
        if amount > 0:
            change_out = create_transaction_output(issuing_address, amount)
            txouts = txouts + [change_out]

        txouts = txouts + [cert_out]
        tx = CMutableTransaction(txins, txouts)

        # this is the transaction for a recipient, unsigned
        hextx = hexlify(tx.serialize())
        with open(certificate_metadata.unsigned_tx_file_name, 'wb') as out_file:
            out_file.write(bytes(hextx, 'utf-8'))

        logging.info(
            'Created unsigned tx for recipient; last_input=%s', last_input)
        return last_input
コード例 #14
0
    def create_transactions(self, revocation_address):
        """
        Create the batch Bitcoin transaction
        :param revocation_address:
        :return:
        """
        self.tree.make_tree()

        spendables = self.connector.get_unspent_outputs(self.issuing_address)
        if not spendables:
            error_message = 'No money to spend at address {}'.format(
                self.issuing_address)
            logging.error(error_message)
            raise InsufficientFundsError(error_message)

        last_input = spendables[-1]

        op_return_value = unhexlify(self.tree.get_merkle_root())

        tx_outs = self.build_recipient_tx_outs()
        tx_outs.append(
            tx_utils.create_transaction_output(
                revocation_address,
                self.tx_cost_constants.get_minimum_output_coin()))

        transaction = tx_utils.create_trx(op_return_value, self.total,
                                          self.issuing_address, tx_outs,
                                          last_input)

        transaction_data = TransactionData(
            uid=self.batch_id,
            tx=transaction,
            tx_input=last_input,
            op_return_value=hexlify(op_return_value),
            batch_metadata=self.batch_metadata)

        return [transaction_data]
コード例 #15
0
    def issue_on_blockchain(self, revocation_address, issuing_transaction_cost):
        """
        Issue the certificates on the Bitcoin blockchain
        :param revocation_address:
        :param issuing_transaction_cost:
        :return:
        """
        transactions_data = self.create_transactions(revocation_address, issuing_transaction_cost)
        for transaction_data in transactions_data:
            # persist the transaction in case broadcasting fails
            hex_tx = hexlify(transaction_data.tx.serialize())
            with open(transaction_data.unsigned_tx_file_name, 'w') as out_file:
                out_file.write(hex_tx)

            # sign transaction and persist result
            signed_tx = trx_utils.sign_tx(hex_tx, transaction_data.tx_input)

            # log the actual byte count
            tx_byte_count = trx_utils.get_byte_count(signed_tx)
            logging.info('The actual transaction size is %d bytes', tx_byte_count)

            signed_hextx = signed_tx.as_hex()
            with open(transaction_data.signed_tx_file_name, 'w') as out_file:
                out_file.write(signed_hextx)

            # verify transaction before broadcasting
            trx_utils.verify_transaction(signed_hextx, transaction_data.op_return_value)

            # send tx and persist txid
            tx_id = broadcast_tx(signed_tx)
            if tx_id:
                logging.info('Broadcast transaction with txid %s', tx_id)
            else:
                logging.warning(
                    'could not broadcast transaction but you can manually do it! signed hextx=%s', signed_hextx)

            self.finish_tx(transaction_data.sent_tx_file_name, tx_id)
コード例 #16
0
ファイル: connectors.py プロジェクト: sbepstein/cert-issuer
def bitcoind_broadcast(hextx):
    tx = CTransaction.deserialize(unhexlify(hextx))
    txid = bitcoin.rpc.Proxy().sendrawtransaction(tx)
    return hexlify(txid)
コード例 #17
0
ファイル: connectors.py プロジェクト: tonypius/cert-issuer
 def broadcast_tx(self, transaction):
     as_hex = transaction.as_hex()
     transaction = CTransaction.deserialize(unhexlify(as_hex))
     tx_id = bitcoin.rpc.Proxy().sendrawtransaction(transaction)
     # reverse endianness for bitcoind
     return hexlify(bytearray(tx_id)[::-1])
コード例 #18
0
 def broadcast_tx(self, transaction):
     as_hex = transaction.as_hex()
     transaction = CTransaction.deserialize(unhexlify(as_hex))
     tx_id = bitcoin.rpc.Proxy().sendrawtransaction(transaction)
     # reverse endianness for bitcoind
     return hexlify(bytearray(tx_id)[::-1])
コード例 #19
0
ファイル: connectors.py プロジェクト: Akiiki/cert-issuer
def bitcoind_broadcast(hextx):
    tx = CTransaction.deserialize(unhexlify(hextx))
    txid = bitcoin.rpc.Proxy().sendrawtransaction(tx)
    return hexlify(txid)
コード例 #20
0
def bitcoind_broadcast(hextx):
    tx = CTransaction.deserialize(unhexlify(hextx))
    txid = bitcoin.rpc.Proxy().sendrawtransaction(tx)
    # reverse endianness for bitcoind
    return hexlify(bytearray(txid)[::-1])
コード例 #21
0
    def issue_on_blockchain(self):
        """
        Issue the certificates on the Bitcoin blockchain
        :param revocation_address:
        :return:
        """

        self.tree.make_tree()
        op_return_value_bytes = unhexlify(self.tree.get_merkle_root())
        op_return_value = hexlify(op_return_value_bytes)

        for attempt_number in range(0, self.max_retry):
            try:
                if self.prepared_inputs:
                    inputs = self.prepared_inputs
                else:
                    spendables = self.connector.get_unspent_outputs(
                        self.secure_signer.issuing_address)
                    if not spendables:
                        error_message = 'No money to spend at address {}'.format(
                            self.secure_signer.issuing_address)
                        logging.error(error_message)
                        raise InsufficientFundsError(error_message)

                    cost = self.transaction_handler.estimate_cost_for_certificate_batch(
                    )
                    current_total = 0
                    inputs = []
                    random.shuffle(spendables)
                    for s in spendables:
                        inputs.append(s)
                        current_total += s.coin_value
                        if current_total > cost:
                            break

                tx = self.transaction_handler.create_transaction(
                    inputs, op_return_value_bytes)
                hex_tx = hexlify(tx.serialize())
                logging.info('Unsigned hextx=%s', hex_tx)

                prepared_tx = tx_utils.prepare_tx_for_signing(hex_tx, inputs)
                with FinalizableSigner(self.secure_signer) as signer:
                    signed_tx = signer.sign_transaction(prepared_tx)

                # log the actual byte count
                tx_byte_count = tx_utils.get_byte_count(signed_tx)
                logging.info('The actual transaction size is %d bytes',
                             tx_byte_count)

                signed_hextx = signed_tx.as_hex()
                logging.info('Signed hextx=%s', signed_hextx)

                # verify transaction before broadcasting
                tx_utils.verify_transaction(signed_hextx, op_return_value)

                # send tx and persist txid
                tx_id = self.connector.broadcast_tx(signed_tx)
                logging.info('Broadcast transaction with txid %s', tx_id)
                return tx_id
            except BroadcastError:
                logging.warning(
                    'Failed broadcast reattempts. Trying to recreate transaction. This is attempt number %d',
                    attempt_number)
        logging.error(
            'All attempts to broadcast failed. Try rerunning issuer.')
        raise BroadcastError(
            'All attempts to broadcast failed. Try rerunning issuer.')