From b25fe03008d48f1886d1d257f43df66331740999 Mon Sep 17 00:00:00 2001 From: Shawn Wilson Date: Mon, 23 Jul 2018 13:44:50 -0500 Subject: [PATCH] Use automatic detection for encodable message string vs raw bytes. Use a constant for BCH to satoshi multiplier. --- HISTORY.rst | 3 ++- bitcash/__init__.py | 2 +- bitcash/network/services.py | 22 +++++++++++---------- bitcash/transaction.py | 6 ++++-- bitcash/wallet.py | 38 ++++++++----------------------------- 5 files changed, 27 insertions(+), 44 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 7307b334..69c4bb2e 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -9,7 +9,8 @@ Unreleased (see `master `_) contains some common details of the transaction. - Allow raw byte string to be used as transaction OP_RETURN - message with new 'bytes=True' parameter. Increase message + message: automatic detection assumes a byte-like object when + message does not have an encode() function. Increase message size to 220 bytes. - NetworkAPI.get_tx_amount() is now working and properly handles diff --git a/bitcash/__init__.py b/bitcash/__init__.py index be098daa..76baff10 100644 --- a/bitcash/__init__.py +++ b/bitcash/__init__.py @@ -3,4 +3,4 @@ from bitcash.network.services import set_service_timeout from bitcash.wallet import Key, PrivateKey, PrivateKeyTestnet, wif_to_key -__version__ = '0.5.2.3' +__version__ = '0.5.2.4' diff --git a/bitcash/network/services.py b/bitcash/network/services.py index 476cef01..161e9db7 100644 --- a/bitcash/network/services.py +++ b/bitcash/network/services.py @@ -10,6 +10,8 @@ DEFAULT_TIMEOUT = 30 +BCH_TO_SAT_MULTIPLIER = 100000000 + def set_service_timeout(seconds): global DEFAULT_TIMEOUT @@ -48,9 +50,9 @@ def get_transaction(cls, txid): response = r.json(parse_float=Decimal) tx = Transaction(response['txid'], response['blockheight'], - (Decimal(response['valueIn'])*100000000).normalize(), - (Decimal(response['valueOut'])*100000000).normalize(), - (Decimal(response['fees'])*100000000).normalize()) + (Decimal(response['valueIn']) * BCH_TO_SAT_MULTIPLIER).normalize(), + (Decimal(response['valueOut']) * BCH_TO_SAT_MULTIPLIER).normalize(), + (Decimal(response['fees']) * BCH_TO_SAT_MULTIPLIER).normalize()) for txin in response['vin']: part = TxPart(txin['addr'], txin['valueSat'], txin['scriptSig']['asm']) @@ -62,7 +64,7 @@ def get_transaction(cls, txid): addr = txout['scriptPubKey']['addresses'][0] part = TxPart(addr, - (Decimal(txout['value'])*100000000).normalize(), + (Decimal(txout['value']) * BCH_TO_SAT_MULTIPLIER).normalize(), txout['scriptPubKey']['asm']) tx.add_output(part) @@ -74,7 +76,7 @@ def get_tx_amount(cls, txid, txindex): if r.status_code != 200: # pragma: no cover raise ConnectionError response = r.json(parse_float=Decimal) - return (Decimal(response['vout'][txindex]['value'])*100000000).normalize() + return (Decimal(response['vout'][txindex]['value']) * BCH_TO_SAT_MULTIPLIER).normalize() @classmethod def get_unspent(cls, address): @@ -184,9 +186,9 @@ def get_transaction_testnet(cls, txid): response = r.json(parse_float=Decimal) tx = Transaction(response['txid'], response['blockheight'], - (Decimal(response['valueIn'])*100000000).normalize(), - (Decimal(response['valueOut'])*100000000).normalize(), - (Decimal(response['fees'])*100000000).normalize()) + (Decimal(response['valueIn']) * BCH_TO_SAT_MULTIPLIER).normalize(), + (Decimal(response['valueOut']) * BCH_TO_SAT_MULTIPLIER).normalize(), + (Decimal(response['fees']) * BCH_TO_SAT_MULTIPLIER).normalize()) for txin in response['vin']: part = TxPart(txin['addr'], txin['valueSat'], txin['scriptSig']['asm']) @@ -198,7 +200,7 @@ def get_transaction_testnet(cls, txid): addr = txout['scriptPubKey']['addresses'][0] part = TxPart(addr, - (Decimal(txout['value'])*100000000).normalize(), + (Decimal(txout['value']) * BCH_TO_SAT_MULTIPLIER).normalize(), txout['scriptPubKey']['asm']) tx.add_output(part) @@ -210,7 +212,7 @@ def get_tx_amount_testnet(cls, txid, txindex): if r.status_code != 200: # pragma: no cover raise ConnectionError response = r.json(parse_float=Decimal) - return (Decimal(response['vout'][txindex]['value'])*100000000).normalize() + return (Decimal(response['vout'][txindex]['value']) * BCH_TO_SAT_MULTIPLIER).normalize() @classmethod def get_unspent_testnet(cls, address): diff --git a/bitcash/transaction.py b/bitcash/transaction.py index 18f9130a..90eb4687 100644 --- a/bitcash/transaction.py +++ b/bitcash/transaction.py @@ -90,7 +90,7 @@ def estimate_tx_fee(n_in, n_out, satoshis, compressed): return estimated_fee -def sanitize_tx_data(unspents, outputs, fee, leftover, combine=True, message=None, bytes=False, compressed=True): +def sanitize_tx_data(unspents, outputs, fee, leftover, combine=True, message=None, compressed=True): """ sanitize_tx_data() @@ -113,8 +113,10 @@ def sanitize_tx_data(unspents, outputs, fee, leftover, combine=True, message=Non messages = [] if message: - if not bytes: + try: message = message.encode('utf-8') + except AttributeError: + pass # assume message is already a bytes-like object message_chunks = chunk_data(message, MESSAGE_LIMIT) diff --git a/bitcash/wallet.py b/bitcash/wallet.py index 2a3ce5e7..e6aeb7dd 100644 --- a/bitcash/wallet.py +++ b/bitcash/wallet.py @@ -206,7 +206,7 @@ def get_transactions(self): return self.transactions def create_transaction(self, outputs, fee=None, leftover=None, combine=True, - message=None, bytes=False, unspents=None): # pragma: no cover + message=None, unspents=None): # pragma: no cover """Creates a signed P2PKH transaction. :param outputs: A sequence of outputs you wish to send in the form @@ -232,9 +232,6 @@ def create_transaction(self, outputs, fee=None, leftover=None, combine=True, stored in the blockchain forever. Due to size limits, each message will be stored in chunks of 220 bytes. :type message: ``str`` - :param bytes: Whether or not the supplied message is already bytes. If - false (default), message is automatically encoded to UTF-8. - :type bytes: ``bool`` :param unspents: The UTXOs to use as the inputs. By default Bitcash will communicate with the blockchain itself. :type unspents: ``list`` of :class:`~bitcash.network.meta.Unspent` @@ -249,14 +246,13 @@ def create_transaction(self, outputs, fee=None, leftover=None, combine=True, leftover or self.address, combine=combine, message=message, - bytes=bytes, compressed=self.is_compressed() ) return create_p2pkh_transaction(self, unspents, outputs) def send(self, outputs, fee=None, leftover=None, combine=True, - message=None, bytes=False, unspents=None): # pragma: no cover + message=None, unspents=None): # pragma: no cover """Creates a signed P2PKH transaction and attempts to broadcast it on the blockchain. This accepts the same arguments as :func:`~bitcash.PrivateKey.create_transaction`. @@ -284,9 +280,6 @@ def send(self, outputs, fee=None, leftover=None, combine=True, stored in the blockchain forever. Due to size limits, each message will be stored in chunks of 220 bytes. :type message: ``str`` - :param bytes: Whether or not the supplied message is already bytes. If - false (default), message is automatically encoded to UTF-8. - :type bytes: ``bool`` :param unspents: The UTXOs to use as the inputs. By default Bitcash will communicate with the blockchain itself. :type unspents: ``list`` of :class:`~bitcash.network.meta.Unspent` @@ -295,7 +288,7 @@ def send(self, outputs, fee=None, leftover=None, combine=True, """ tx_hex = self.create_transaction( - outputs, fee=fee, leftover=leftover, combine=combine, message=message, bytes=bytes, unspents=unspents + outputs, fee=fee, leftover=leftover, combine=combine, message=message, unspents=unspents ) NetworkAPI.broadcast_tx(tx_hex) @@ -304,7 +297,7 @@ def send(self, outputs, fee=None, leftover=None, combine=True, @classmethod def prepare_transaction(cls, address, outputs, compressed=True, fee=None, leftover=None, - combine=True, message=None, bytes=False, unspents=None): # pragma: no cover + combine=True, message=None, unspents=None): # pragma: no cover """Prepares a P2PKH transaction for offline signing. :param address: The address the funds will be sent from. @@ -335,9 +328,6 @@ def prepare_transaction(cls, address, outputs, compressed=True, fee=None, leftov stored in the blockchain forever. Due to size limits, each message will be stored in chunks of 220 bytes. :type message: ``str`` - :param bytes: Whether or not the supplied message is already bytes. If - false (default), message is automatically encoded to UTF-8. - :type bytes: ``bool`` :param unspents: The UTXOs to use as the inputs. By default Bitcash will communicate with the blockchain itself. :type unspents: ``list`` of :class:`~bitcash.network.meta.Unspent` @@ -351,7 +341,6 @@ def prepare_transaction(cls, address, outputs, compressed=True, fee=None, leftov leftover or address, combine=combine, message=message, - bytes=bytes, compressed=compressed ) @@ -510,7 +499,7 @@ def get_transactions(self): return self.transactions def create_transaction(self, outputs, fee=None, leftover=None, combine=True, - message=None, bytes=False, unspents=None): + message=None, unspents=None): """Creates a signed P2PKH transaction. :param outputs: A sequence of outputs you wish to send in the form @@ -536,9 +525,6 @@ def create_transaction(self, outputs, fee=None, leftover=None, combine=True, stored in the blockchain forever. Due to size limits, each message will be stored in chunks of 220 bytes. :type message: ``str`` - :param bytes: Whether or not the supplied message is already bytes. If - false (default), message is automatically encoded to UTF-8. - :type bytes: ``bool`` :param unspents: The UTXOs to use as the inputs. By default Bitcash will communicate with the testnet blockchain itself. :type unspents: ``list`` of :class:`~bitcash.network.meta.Unspent` @@ -553,14 +539,13 @@ def create_transaction(self, outputs, fee=None, leftover=None, combine=True, leftover or self.address, combine=combine, message=message, - bytes=bytes, compressed=self.is_compressed() ) return create_p2pkh_transaction(self, unspents, outputs) def send(self, outputs, fee=None, leftover=None, combine=True, - message=None, bytes=False, unspents=None): + message=None, unspents=None): """Creates a signed P2PKH transaction and attempts to broadcast it on the testnet blockchain. This accepts the same arguments as :func:`~bitcash.PrivateKeyTestnet.create_transaction`. @@ -588,9 +573,6 @@ def send(self, outputs, fee=None, leftover=None, combine=True, stored in the blockchain forever. Due to size limits, each message will be stored in chunks of 220 bytes. :type message: ``str`` - :param bytes: Whether or not the supplied message is already bytes. If - false (default), message is automatically encoded to UTF-8. - :type bytes: ``bool`` :param unspents: The UTXOs to use as the inputs. By default Bitcash will communicate with the testnet blockchain itself. :type unspents: ``list`` of :class:`~bitcash.network.meta.Unspent` @@ -599,7 +581,7 @@ def send(self, outputs, fee=None, leftover=None, combine=True, """ tx_hex = self.create_transaction( - outputs, fee=fee, leftover=leftover, combine=combine, message=message, bytes=bytes, unspents=unspents + outputs, fee=fee, leftover=leftover, combine=combine, message=message, unspents=unspents ) NetworkAPI.broadcast_tx_testnet(tx_hex) @@ -608,7 +590,7 @@ def send(self, outputs, fee=None, leftover=None, combine=True, @classmethod def prepare_transaction(cls, address, outputs, compressed=True, fee=None, leftover=None, - combine=True, message=None, bytes=False, unspents=None): + combine=True, message=None, unspents=None): """Prepares a P2PKH transaction for offline signing. :param address: The address the funds will be sent from. @@ -639,9 +621,6 @@ def prepare_transaction(cls, address, outputs, compressed=True, fee=None, leftov stored in the blockchain forever. Due to size limits, each message will be stored in chunks of 220 bytes. :type message: ``str`` - :param bytes: Whether or not the supplied message is already bytes. If - false (default), message is automatically encoded to UTF-8. - :type bytes: ``bool`` :param unspents: The UTXOs to use as the inputs. By default Bitcash will communicate with the blockchain itself. :type unspents: ``list`` of :class:`~bitcash.network.meta.Unspent` @@ -655,7 +634,6 @@ def prepare_transaction(cls, address, outputs, compressed=True, fee=None, leftov leftover or address, combine=combine, message=message, - bytes=bytes, compressed=compressed )