예제 #1
0
def print_transaction(wt):
    tx_dict = {
        'network':
        wt.network.name,
        'fee':
        wt.fee,
        'raw':
        wt.raw_hex(),
        'outputs': [{
            'address': o.address,
            'value': o.value
        } for o in wt.outputs],
        'inputs': [{
            'prev_hash':
            to_hexstring(i.prev_hash),
            'output_n':
            struct.unpack('>I', i.output_n)[0],
            'address':
            i.address,
            'signatures': [{
                'signature': to_hexstring(s['signature']),
                'sig_der': to_hexstring(s['sig_der']),
                'pub_key': to_hexstring(s['pub_key']),
            } for s in i.signatures],
            'value':
            i.value
        } for i in wt.inputs]
    }
    pprint(tx_dict)
예제 #2
0
    def as_dict(self):
        """
        Get representation of current Block as dictionary.

        :return dict:
        """
        return {
            'block_hash':
            to_hexstring(self.block_hash),
            'height':
            self.height,
            'version':
            self.version_int,
            'prev_block':
            None if not self.prev_block else to_hexstring(self.prev_block),
            'merkle_root':
            to_hexstring(self.merkle_root),
            'timestamp':
            self.time,
            'bits':
            self.bits_int,
            'nonce':
            self.nonce_int,
            'target':
            self.target_hex,
            'difficulty':
            self.difficulty,
            'tx_count':
            self.tx_count,
            'transactions':
            self.transactions,
            'confirmations':
            self.confirmations
        }
예제 #3
0
def prefix_search(wif, network=None):
    """
    Extract network, script type and public/private information from WIF prefix.

    :param wif: WIF string or prefix in bytes or hexadecimal string
    :type wif: str, bytes
    :param network: Limit search to specified network
    :type network: str

    :return dict:
    """

    key_hex = change_base(wif, 58, 16)
    if not key_hex:
        key_hex = to_hexstring(wif)
    prefix = key_hex[:8].upper()
    matches = []
    for nw in NETWORK_DEFINITIONS:
        if network is not None and nw != network:
            continue
        data = NETWORK_DEFINITIONS[nw]
        for pf in data['prefixes_wif']:
            if pf[1] == prefix:
                matches.append({
                    'prefix': prefix,
                    'is_private': True if pf[0] == 'private' else False,
                    'prefix_str': pf[2],
                    'network': nw,
                    'script_types': pf[3]
                })
    return matches
예제 #4
0
def network_by_value(field, value):
    """
    Return all networks for field and (prefix) value.
    
    Example, get available networks for WIF or address prefix

    >>> network_by_value('prefix_wif', 'B0')
    ['litecoin', 'litecoin_legacy']
    >>> network_by_value('prefix_address', '6f')
    ['testnet', 'litecoin_testnet']

    This method does not work for HD prefixes, use 'wif_prefix_search' instead

    >>> network_by_value('prefix_address', '043587CF')
    []
    
    :param field: Prefix name from networks definitions (networks.json)
    :type field: str
    :param value: Value of network prefix
    :type value: str, bytes

    :return list: Of network name strings 
    """
    nws = [(nv, NETWORK_DEFINITIONS[nv]['priority'])
           for nv in NETWORK_DEFINITIONS
           if NETWORK_DEFINITIONS[nv][field] == value]
    if not nws:
        try:
            value = to_hexstring(value).upper()
        except TypeError:
            pass
        nws = [(nv, NETWORK_DEFINITIONS[nv]['priority'])
               for nv in NETWORK_DEFINITIONS
               if NETWORK_DEFINITIONS[nv][field] == value]
    return [nw[0] for nw in sorted(nws, key=lambda x: x[1], reverse=True)]
예제 #5
0
 def getutxos(self, address, after_txid='', limit=MAX_TRANSACTIONS):
     utxos = []
     utxo_list = []
     next_link = ''
     while True:
         variables = {'limit': REQ_LIMIT, 'next': next_link, 'dir': 'asc'}
         res = self.compose_request('address', 'unspent', address, variables=variables)
         next_link = res['paging']['next']
         for utxo in res['unspent']:
             utxo_list.append(utxo['txid'])
             if utxo['txid'] == after_txid:
                 utxo_list = []
         if not next_link or len(utxos) > REQ_LIMIT_TOTAL:
             break
     for txid in utxo_list[:limit]:
         t = self.gettransaction(txid)
         for utxo in t.outputs:
             if utxo.address != address:
                 continue
             utxos.append(
                 {
                     'address': utxo.address,
                     'tx_hash': t.hash,
                     'confirmations': t.confirmations,
                     'output_n': utxo.output_n,
                     'input_n': 0,
                     'block_height': t.block_height,
                     'fee': t.fee,
                     'size': t.size,
                     'value': utxo.value,
                     'script': to_hexstring(utxo.lock_script),
                     'date': t.date
                 })
     return utxos
예제 #6
0
def network_by_value(field, value):
    """
    Return all networks for field and (prefix) value.
    
    For Example:
        network_by_value('prefix_wif', 'B0')
        
    Returns:
        ['litecoin']
    
    :param field: Prefix name from networks definitions (networks.json)
    :type field: str
    :param value: Value of network prefix
    :type value: str, bytes

    :return list: Of network name strings 
    """
    nws = [(nv, NETWORK_DEFINITIONS[nv]['priority'])
           for nv in NETWORK_DEFINITIONS
           if NETWORK_DEFINITIONS[nv][field] == value]
    if not nws:
        try:
            value = to_hexstring(value).upper()
        except TypeError:
            pass
        nws = [(nv, NETWORK_DEFINITIONS[nv]['priority'])
               for nv in NETWORK_DEFINITIONS
               if NETWORK_DEFINITIONS[nv][field] == value]
    return [nw[0] for nw in sorted(nws, key=lambda x: x[1], reverse=True)]
예제 #7
0
 def gettransaction(self, txid):
     tx = self.proxy.getrawtransaction(txid, 1)
     t = Transaction.import_raw(tx['hex'], network=self.network)
     t.confirmations = tx['confirmations']
     if t.confirmations:
         t.status = 'confirmed'
         t.verified = True
     for i in t.inputs:
         if i.prev_hash == b'\x00' * 32:
             i.value = t.output_total
             i.script_type = 'coinbase'
             continue
         txi = self.proxy.getrawtransaction(to_hexstring(i.prev_hash), 1)
         i.value = int(
             round(
                 float(txi['vout'][i.output_n_int]['value']) /
                 self.network.denominator))
     for o in t.outputs:
         o.spent = None
     t.block_hash = tx['blockhash']
     t.version = struct.pack('>L', tx['version'])
     t.date = datetime.utcfromtimestamp(tx['blocktime'])
     t.hash = txid
     t.update_totals()
     return t
예제 #8
0
def network_values_for(field, output_as='default'):
    """
    Return all prefixes mentioned field, i.e.: prefix_wif, prefix_address_p2sh, etc

    >>> network_values_for('prefix_wif')
    [b'\x99', b'\x80', b'\xef', b'\xb0', b'\xb0', b'\xef', b'\xcc', b'\xef']
    >>> network_values_for('prefix_address_p2sh')
    [b'\x95', b'\x05', b'\xc4', b'2', b'\x05', b':', b'\x10', b'\x13']

    :param field: Prefix name from networks definitions (networks.json)
    :type field: str
    :param output_as: Output as string or hexstring. Default is string or hexstring depending on field type.
    :type output_as: str
    
    :return str: 
    """
    r = [
        _format_value(field, nv[field]) for nv in NETWORK_DEFINITIONS.values()
    ]
    if output_as == 'str':
        return [normalize_var(i) for i in r]
    elif output_as == 'hex':
        return [to_hexstring(i) for i in r]
    else:
        return r
예제 #9
0
파일: bitcoind.py 프로젝트: d42/bitcoinlib
 def _parse_transaction(self, tx, block_height=None, get_input_values=True):
     t = Transaction.import_raw(tx['hex'], network=self.network)
     t.confirmations = None if 'confirmations' not in tx else tx[
         'confirmations']
     if t.confirmations or block_height:
         t.status = 'confirmed'
         t.verified = True
     for i in t.inputs:
         if i.prev_hash == b'\x00' * 32:
             i.script_type = 'coinbase'
             continue
         if get_input_values:
             txi = self.proxy.getrawtransaction(to_hexstring(i.prev_hash),
                                                1)
             i.value = int(
                 round(
                     float(txi['vout'][i.output_n_int]['value']) /
                     self.network.denominator))
     for o in t.outputs:
         o.spent = None
     t.block_hash = tx.get('block_hash', tx['txid'])  # FIXME, use only one
     t.block_height = block_height
     t.version = struct.pack('>L', tx['version'])
     t.date = datetime.utcfromtimestamp(tx['time'])
     t.update_totals()
     return t
예제 #10
0
    def _parse_transaction(self, tx, block_height=None, get_input_values=True):
        t = Transaction.import_raw(tx['hex'], network=self.network)
        t.confirmations = None if 'confirmations' not in tx else tx['confirmations']
        t.status = 'unconfirmed'
        for i in t.inputs:
            if i.prev_hash == b'\x00' * 32:
                i.script_type = 'coinbase'
                continue
            if get_input_values:
                txi = self.proxy.getrawtransaction(to_hexstring(i.prev_hash), 1)
                i.value = int(round(float(txi['vout'][i.output_n_int]['value']) / self.network.denominator))
        for o in t.outputs:
            o.spent = None

        t.block_hash = tx.get('blockhash', '')
        if not block_height and t.block_hash:
            block_height = self.proxy.getblock(t.block_hash, 1)['height']
        t.block_height = block_height
        if not t.confirmations and block_height is not None:
            if not self.latest_block:
                self.latest_block = self.blockcount()
            t.confirmations = (self.latest_block - block_height) + 1
        if t.confirmations or block_height:
            t.status = 'confirmed'
            t.verified = True

        t.version = struct.pack('>L', tx['version'])
        t.date = None if 'time' not in tx else datetime.utcfromtimestamp(tx['time'])
        t.update_totals()
        return t
예제 #11
0
def network_by_value(field, value):
    """
    Return all networks for field and (prefix) value.
    
    For Example:
        network_by_value('prefix_wif', 'B0')
        
    Returns:
        ['litecoin']
    
    :param field: Prefix name from networks definitions (networks.json)
    :type field: str
    :param value: Value of network prefix
    :type value: str, bytes
    
    :return list: Of network name strings 
    """
    try:
        value = to_hexstring(value).upper()
    except:
        pass
    return [
        nv for nv in NETWORK_DEFINITIONS
        if NETWORK_DEFINITIONS[nv][field] == value
    ]
예제 #12
0
    def getutxos(self, address, after_txid='', limit=MAX_TRANSACTIONS):
        # First get all transactions for this address from the blockchain
        from bitcoinlib.services.services import Service
        srv = Service(network=self.network.name, providers=['bcoin'])
        txs = srv.gettransactions(address, limit=25)

        # Fail if large number of transactions are found
        if not srv.complete:
            raise ClientError(
                "If not all transactions known, we cannot determine utxo's. "
                "Increase limit or use other provider")

        utxos = []
        for tx in txs:
            for unspent in tx.outputs:
                if unspent.address != address:
                    continue
                if not srv.isspent(tx.txid, unspent.output_n):
                    utxos.append({
                        'address': unspent.address,
                        'tx_hash': tx.txid,
                        'confirmations': tx.confirmations,
                        'output_n': unspent.output_n,
                        'input_n': 0,
                        'block_height': tx.block_height,
                        'fee': tx.fee,
                        'size': tx.size,
                        'value': unspent.value,
                        'script': to_hexstring(unspent.lock_script),
                        'date': tx.date,
                    })
                    if tx.txid == after_txid:
                        utxos = []
        return utxos[:limit]
예제 #13
0
def wif_prefix_search(wif, witness_type=None, multisig=None, network=None):
    """
    Extract network, script type and public/private information from HDKey WIF or WIF prefix.

    Example, get bitcoin 'xprv' info:

    >>> wif_prefix_search('0488ADE4', network='bitcoin', multisig=False)
    [{'prefix': '0488ADE4', 'is_private': True, 'prefix_str': 'xprv', 'network': 'bitcoin', 'witness_type': 'legacy', 'multisig': False, 'script_type': 'p2pkh'}]

    Or retreive info with full WIF string:

    >>> wif_prefix_search('xprv9wTYmMFdV23N21MM6dLNavSQV7Sj7meSPXx6AV5eTdqqGLjycVjb115Ec5LgRAXscPZgy5G4jQ9csyyZLN3PZLxoM1h3BoPuEJzsgeypdKj', network='bitcoin', multisig=False)
    [{'prefix': '0488ADE4', 'is_private': True, 'prefix_str': 'xprv', 'network': 'bitcoin', 'witness_type': 'legacy', 'multisig': False, 'script_type': 'p2pkh'}]

    Can return multiple items if no network is specified:

    >>> [nw['network'] for nw in wif_prefix_search('0488ADE4', multisig=True)]
    ['bitcoin', 'dash']

    :param wif: WIF string or prefix in bytes or hexadecimal string
    :type wif: str, bytes
    :param witness_type: Limit search to specific witness type
    :type witness_type: str
    :param multisig: Limit search to multisig: false, true or None for both. Default is both
    :type multisig: bool
    :param network: Limit search to specified network
    :type network: str

    :return dict:
    """

    key_hex = ''
    if len(wif) > 8:
        try:
            key_hex = change_base(wif, 58, 16)
        except:
            pass
    else:
        key_hex = wif
    if not key_hex:
        key_hex = to_hexstring(wif)
    prefix = key_hex[:8].upper()
    matches = []
    for nw in NETWORK_DEFINITIONS:
        if network is not None and nw != network:
            continue
        data = NETWORK_DEFINITIONS[nw]
        for pf in data['prefixes_wif']:
            if pf[0] == prefix and (multisig is None or pf[3] is None or pf[3] == multisig) and \
                    (witness_type is None or pf[4] is None or pf[4] == witness_type):
                matches.append({
                    'prefix': prefix,
                    'is_private': True if pf[2] == 'private' else False,
                    'prefix_str': pf[1],
                    'network': nw,
                    'witness_type': pf[4],
                    'multisig': pf[3],
                    'script_type': pf[5]
                })
    return matches
예제 #14
0
    def store_transaction(self, t, order_n=None, commit=True):
        """
        Store transaction in cache. Use order number to determine order in a block

        :param t: Transaction
        :type t: Transaction
        :param order_n: Order in block
        :type order_n: int
        :param commit: Commit transaction to database. Default is True. Can be disabled if a larger number of transactions are added to cache, so you can commit outside this method.

        :return:
        """
        if not self.cache_enabled():
            return
        # Only store complete and confirmed transaction in cache
        if not t.txid:    # pragma: no cover
            _logger.info("Caching failure tx: Missing transaction hash")
            return False
        elif not t.date or not t.block_height or not t.network:
            _logger.info("Caching failure tx: Incomplete transaction missing date, block height or network info")
            return False
        elif not t.coinbase and [i for i in t.inputs if not i.value]:
            _logger.info("Caching failure tx: One the transaction inputs has value 0")
            return False
        raw_hex = None
        if CACHE_STORE_RAW_TRANSACTIONS:
            raw_hex = t.raw_hex()
            if not raw_hex:    # pragma: no cover
                _logger.info("Caching failure tx: Raw hex missing in transaction")
                return False
        if self.session.query(DbCacheTransaction).filter_by(txid=t.txid).count():
            return
        new_tx = DbCacheTransaction(txid=t.txid, date=t.date, confirmations=t.confirmations,
                                    block_height=t.block_height, block_hash=t.block_hash, network_name=t.network.name,
                                    fee=t.fee, raw=raw_hex, order_n=order_n)
        self.session.add(new_tx)
        for i in t.inputs:
            if i.value is None or i.address is None or i.output_n is None:    # pragma: no cover
                _logger.info("Caching failure tx: Input value, address or output_n missing")
                return False
            new_node = DbCacheTransactionNode(txid=t.txid, address=i.address, output_n=i.index_n, value=i.value,
                                              is_input=True)
            self.session.add(new_node)
        for o in t.outputs:
            if o.value is None or o.address is None or o.output_n is None:    # pragma: no cover
                _logger.info("Caching failure tx: Output value, address, spent info or output_n missing")
                return False
            new_node = DbCacheTransactionNode(
                txid=t.txid, address=o.address, output_n=o.output_n, value=o.value, is_input=False, spent=o.spent,
                spending_txid=None if not o.spending_txid else to_hexstring(o.spending_txid),
                spending_index_n=o.spending_index_n)
            self.session.add(new_node)

        if commit:
            try:
                self.commit()
                _logger.info("Added transaction %s to cache" % t.txid)
            except Exception as e:    # pragma: no cover
                _logger.warning("Caching failure tx: %s" % e)
예제 #15
0
 def sign(self, msg):
     """
         Sign a message with private key, Return signature
     """
     priv = PrivateKey(self.key.private_byte, raw=True)
     sig = priv.ecdsa_sign(msg)
     h = priv.ecdsa_serialize_compact(sig)
     return self.key.public_hex, encoding.to_hexstring(h)
예제 #16
0
    def sendrawtransaction(self, rawtx):
        """
        Push a raw transaction to the network

        :param rawtx: Raw transaction as hexstring
        :type rawtx: str, bytes

        :return dict: Send transaction result
        """
        rawtx = to_hexstring(rawtx)
        return self._provider_execute('sendrawtransaction', rawtx)
예제 #17
0
    def getrawtransaction(self, txid):
        """
        Get a raw transaction by its transaction hash

        :param txid: Transaction identification hash
        :type txid: str, bytes

        :return str: Raw transaction as hexstring
        """
        txid = to_hexstring(txid)
        return self._provider_execute('getrawtransaction', txid)
예제 #18
0
    def gettransaction(self, txid):
        """
        Get a transaction by its transaction hash. Convert to Bitcoinlib transaction object.

        :param txid: Transaction identification hash
        :type txid: str, bytes

        :return Transaction: A single transaction object
        """
        txid = to_hexstring(txid)
        return self._provider_execute('gettransaction', txid)
예제 #19
0
 def test_blocks_parse_genesis(self):
     raw_block = '0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3' \
                 'e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c010100000001000000000000000000' \
                 '0000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d657320303' \
                 '32f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f7574' \
                 '20666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03' \
                 '909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000'
     b = Block.from_raw(to_bytes(raw_block), height=0)
     self.assertEqual(to_hexstring(b.block_hash), '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f')
     self.assertEqual(b.height, 0)
     self.assertEqual(b.version_int, 1)
     self.assertEqual(b.prev_block, 32 * b'\x00')
     self.assertEqual(to_hexstring(b.merkle_root), '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b')
     self.assertEqual(to_hexstring(b.bits), '1d00ffff')
     self.assertEqual(b.time, 1231006505)
     self.assertEqual(to_hexstring(b.nonce), '7c2bac1d')
     self.assertEqual(b.difficulty, 1)
     self.assertEqual(b.target_hex, '00000000ffff0000000000000000000000000000000000000000000000000000')
     self.assertEqual(b.tx_count, 1)
     self.assertEqual(str(b),
                      '<Block(000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f, 0, transactions: 1)>')
예제 #20
0
    def sendrawtransaction(self, rawtx):
        """
        Dummy method to send transactions on the bitcoinlib testnet. The bitcoinlib testnet does not exists,
        so it just returns the transaction hash.

        :param rawtx: A raw transaction hash
        :type rawtx: bytes, str

        :return str: Transaction hash
        """
        txid = to_hexstring(
            hashlib.sha256(hashlib.sha256(
                to_bytes(rawtx)).digest()).digest()[::-1])
        return {'txid': txid, 'response_dict': {}}
예제 #21
0
 def gettransaction(self, txid):
     tx = self.proxy.getrawtransaction(txid, 1)
     t = Transaction.import_raw(tx['hex'], network=self.network)
     t.confirmations = tx['confirmations']
     if t.confirmations:
         t.status = 'confirmed'
         t.verified = True
     for i in t.inputs:
         txi = self.proxy.getrawtransaction(to_hexstring(i.prev_hash), 1)
         value = int(float(txi['vout'][i.output_n_int]['value']) / self.network.denominator)
         i.value = value
     t.block_hash = tx['blockhash']
     t.version = tx['version']
     t.date = datetime.fromtimestamp(tx['blocktime'])
     t.update_totals()
     return t
예제 #22
0
    def getrawtransaction(self, txid):
        """
        Get a raw transaction by its transaction hash

        :param txid: Transaction identification hash
        :type txid: str, bytes

        :return str: Raw transaction as hexstring
        """
        txid = to_hexstring(txid)
        self.results_cache_n = 0
        rawtx = self.cache.getrawtransaction(txid)
        if rawtx:
            self.results_cache_n = 1
            return rawtx
        return self._provider_execute('getrawtransaction', txid)
예제 #23
0
 def test_blocks_parse_block_and_transactions(self):
     b = Block.from_raw(self.rb250000, parse_transactions=True)
     self.assertEqual(to_hexstring(b.block_hash), '000000000000003887df1f29024b06fc2200b55f8af8f35453d7be294df2d214')
     self.assertEqual(b.height, 250000)
     self.assertEqual(b.version_int, 2)
     self.assertEqual(b.prev_block, to_bytes('0000000000000009c2e82d884ec07b4aafb64ca3ef83baca2b6b0b5eb72c8f02'))
     self.assertEqual(b.merkle_root, to_bytes('16ec1eafaca8ca59d182cbf94f29b50b06ac4207b883f380b9bf547fe8fed723'))
     self.assertEqual(b.bits_int, 0x1972dbf2)
     self.assertEqual(b.time, 1375533383)
     self.assertEqual(b.nonce_int, 0x917661)
     self.assertEqual(int(b.difficulty), 37392766)
     self.assertEqual(b.target, 720982641204331278205950312227594303241470815982254303477760)
     self.assertEqual(b.tx_count, 156)
     self.assertEqual(b.transactions[0].txid, '7ae2ab185a6e501753f6e29e5b6a98ba040098acb7c11ffed9430f22ed5263a3')
     self.assertEqual(b.transactions[49].txid, '3b6d97f107cba804270f4d22fafda3295b3bfb735366da6c1473157cc94a5f7c')
     self.assertEqual(b.transactions[122].txid, 'a5cc9bd850b6eedc3e466b3e0f5c85fb640de0a3537259eb0cae761d0a4f78b4')
     self.assertEqual(b.transactions[155].txid, 'e3d6cb87bd37ca53509cdc9ecdabf82ef966d9b25a2598b7de87c8173beb40d5')
예제 #24
0
def network_values_for(field, output_as='default'):
    """
    Return all prefixes mentioned field, i.e.: prefix_wif, prefix_address_p2sh, prefix_hdkey_public, etc
    
    :param field: Prefix name from networks definitions (networks.json)
    :type field: str
    :param output_as: Output as string or hexstring. Default is string or hexstring depending on field type.
    :type output_as: str
    
    :return str: 
    """
    r = [_format_value(field, nv[field]) for nv in NETWORK_DEFINITIONS.values()]
    if output_as == 'str':
        return [normalize_var(i) for i in r]
    elif output_as == 'hex':
        return [to_hexstring(i) for i in r]
    else:
        return r
예제 #25
0
 def gettransaction(self, txid):
     tx = self.compose_request('txs',
                               txid,
                               variables={'includeHex': 'true'})
     t = Transaction.import_raw(tx['hex'], network=self.network)
     # t.hash = to_bytes(txid)
     # t.txid = txid
     if tx['confirmations']:
         t.status = 'confirmed'
         t.date = datetime.strptime(tx['confirmed'][:19],
                                    "%Y-%m-%dT%H:%M:%S")
     else:
         t.status = 'unconfirmed'
     t.confirmations = tx['confirmations']
     t.block_height = tx['block_height'] if tx['block_height'] > 0 else None
     t.block_hash = tx.get('block_hash')
     t.fee = tx['fees']
     t.rawtx = to_bytes(tx['hex'])
     t.size = int(len(tx['hex']) / 2)
     t.network = self.network
     t.input_total = 0
     if len(t.inputs) != len(tx['inputs']):
         raise ClientError(
             "Invalid number of inputs provided. Raw tx: %d, blockcypher: %d"
             % (len(t.inputs), len(tx['inputs'])))
     for n, i in enumerate(t.inputs):
         if not t.coinbase and not (
                 tx['inputs'][n]['output_index'] == i.output_n_int and
                 tx['inputs'][n]['prev_hash'] == to_hexstring(i.prev_hash)):
             raise ClientError(
                 "Transaction inputs do not match raw transaction")
         if 'output_value' in tx['inputs'][n]:
             if not t.coinbase:
                 i.value = tx['inputs'][n]['output_value']
             t.input_total += i.value
     if len(t.outputs) != len(tx['outputs']):
         raise ClientError(
             "Invalid number of outputs provided. Raw tx: %d, blockcypher: %d"
             % (len(t.outputs), len(tx['outputs'])))
     for n, o in enumerate(t.outputs):
         if 'spent_by' in tx['outputs'][n]:
             o.spent = True
             o.spending_txid = tx['outputs'][n]['spent_by']
     return t
예제 #26
0
    def gettransactions(self,
                        address,
                        after_txid='',
                        max_txs=MAX_TRANSACTIONS):
        txs = []
        while True:
            variables = {'limit': LIMIT_TX, 'after': after_txid}
            retries = 0
            while retries < 3:
                try:
                    res = self.compose_request('tx', 'address', address,
                                               variables)
                except ReadTimeout as e:
                    sleep(3)
                    _logger.info("Bcoin client error: %s" % e)
                    retries += 1
                else:
                    break
                finally:
                    if retries == 3:
                        raise ClientError(
                            "Max retries exceeded with bcoin Client")
            for tx in res:
                txs.append(self._parse_transaction(tx))
            if len(txs) >= max_txs:
                break
            if len(res) == LIMIT_TX:
                after_txid = res[LIMIT_TX - 1]['hash']
            else:
                break

        # Check which outputs are spent/unspent for this address
        if not after_txid:
            address_inputs = [(to_hexstring(inp.prev_hash), inp.output_n_int)
                              for ti in [t.inputs for t in txs] for inp in ti
                              if inp.address == address]
            for tx in txs:
                for to in tx.outputs:
                    if to.address != address:
                        continue
                    spent = True if (tx.hash,
                                     to.output_n) in address_inputs else False
                    txs[txs.index(tx)].outputs[to.output_n].spent = spent
        return txs
예제 #27
0
 def test_blocks_parse_block_and_transactions(self):
     b = Block.from_raw(self.rb330000, parse_transactions=True, limit=5)
     self.assertEqual(to_hexstring(b.block_hash), '00000000000000000faabab19f17c0178c754dbed023e6c871dcaf74159c5f02')
     self.assertEqual(b.height, 330000)
     self.assertEqual(b.version_int, 2)
     self.assertEqual(b.prev_block, to_bytes('000000000000000003e20f90920dc065da4a507bcf045f44b9abac7fabff4857'))
     self.assertEqual(b.merkle_root, to_bytes('5a97519772c615a875c12859f447d9c1fea922f7e36bd08e96cc95eee235d28f'))
     self.assertEqual(b.bits_int, 404472624)
     self.assertEqual(b.time, 1415983209)
     self.assertEqual(b.nonce_int, 3756201140)
     self.assertEqual(int(b.difficulty), 39603666252)
     self.assertEqual(b.tx_count, 81)
     self.assertEqual(b.transactions[0].txid, 'dfd63430f8d14f6545117d74b20da63efd4a75c7e28f723b3dead431b88469ee')
     self.assertEqual(b.transactions[4].txid, '717bc8b42f12baf771b6719c2e3b2742925fe3912917c716abef03e35fe49020')
     self.assertEqual(len(b.transactions), 5)
     b.parse_transactions(70)
     self.assertEqual(len(b.transactions), 75)
     b.parse_transactions(10)
     self.assertEqual(len(b.transactions), 81)
     self.assertEqual(b.transactions[80].txid, '7c8483c890942334ecb73db3802f7571b06047b5c15febe3bad11e460065709b')
예제 #28
0
    def gettransaction(self, txid):
        """
        Get a transaction by its transaction hash. Convert to Bitcoinlib transaction object.

        :param txid: Transaction identification hash
        :type txid: str, bytes

        :return Transaction: A single transaction object
        """
        txid = to_hexstring(txid)
        tx = None
        self.results_cache_n = 0

        if self.min_providers <= 1:
            tx = self.cache.gettransaction(txid)
            if tx:
                self.results_cache_n = 1
        if not tx:
            tx = self._provider_execute('gettransaction', txid)
            if len(self.results) and self.min_providers <= 1:
                self.cache.store_transaction(tx, 0)
        return tx
예제 #29
0
 def getutxos(self, address, after_txid='', max_txs=MAX_TRANSACTIONS):
     txs = self.gettransactions(address,
                                after_txid=after_txid,
                                max_txs=max_txs)
     utxos = []
     for tx in txs:
         for unspent in tx.outputs:
             if unspent.address != address:
                 continue
             if not self.isspent(tx.hash, unspent.output_n):
                 utxos.append({
                     'address': unspent.address,
                     'tx_hash': tx.hash,
                     'confirmations': tx.confirmations,
                     'output_n': unspent.output_n,
                     'input_n': 0,
                     'block_height': tx.block_height,
                     'fee': tx.fee,
                     'size': tx.size,
                     'value': unspent.value,
                     'script': to_hexstring(unspent.lock_script),
                     'date': tx.date,
                 })
     return utxos
예제 #30
0
def get_key_format(key, isprivate=None):
    """
    Determins the type (private or public), format and network key.
    
    This method does not validate if a key is valid.

    :param key: Any private or public key
    :type key: str, int, bytes, bytearray
    :param isprivate: Is key private or not?
    :type isprivate: bool
    
    :return dict: Dictionary with format, network and isprivate
    """
    if not key:
        raise BKeyError("Key empty, please specify a valid key")
    key_format = ""
    networks = None

    if isinstance(key, (bytes, bytearray)) and len(key) in [128, 130]:
        key = to_hexstring(key)

    if not (isprivate is None or isinstance(isprivate, bool)):
        raise BKeyError("Attribute 'is_private' must be False or True")
    elif isinstance(key, numbers.Number):
        key_format = 'decimal'
        isprivate = True
    elif isinstance(key, (bytes, bytearray)) and len(key) in [
            33, 65
    ] and key[:1] in [b'\2', b'\3']:
        key_format = 'bin_compressed'
        isprivate = False
    elif isinstance(key, (bytes, bytearray)) and (len(key) in [33, 65]
                                                  and key[:1] == b'\4'):
        key_format = 'bin'
        isprivate = False
    elif isinstance(
            key, (bytes, bytearray)) and len(key) == 33 and key[-1:] == b'\1':
        key_format = 'bin_compressed'
        isprivate = True
    elif isinstance(key, (bytes, bytearray)) and len(key) == 32:
        key_format = 'bin'
        isprivate = True
    elif len(key) == 130 and key[:2] == '04' and not isprivate:
        key_format = 'public_uncompressed'
        isprivate = False
    elif len(key) == 128:
        key_format = 'hex'
        if isprivate is None:
            isprivate = True
    elif len(key) == 66 and key[:2] in ['02', '03'] and not isprivate:
        key_format = 'public'
        isprivate = False
    elif len(key) == 64:
        key_format = 'hex'
        if isprivate is None:
            isprivate = True
    elif len(key) == 66 and key[-2:] in ['01'] and not (isprivate is False):
        key_format = 'hex_compressed'
        isprivate = True
    elif len(key) == 58 and key[:2] == '6P':
        key_format = 'wif_protected'
        isprivate = True
    else:
        try:
            key_hex = change_base(key, 58, 16)
            networks = network_by_value('prefix_wif', key_hex[:2])
            if networks:
                if key_hex[-10:-8] == '01':
                    key_format = 'wif_compressed'
                else:
                    key_format = 'wif'
                isprivate = True
            else:
                networks = network_by_value('prefix_hdkey_private',
                                            key_hex[:8])
                if networks:
                    key_format = 'hdkey_private'
                    isprivate = True
                else:
                    networks = network_by_value('prefix_hdkey_public',
                                                key_hex[:8])
                    if networks:
                        key_format = 'hdkey_public'
                        isprivate = False
                    # TODO: Recognise address key and implement in Key en HDKey classs
                    # else:
                    #     networks = network_by_value('prefix_address_p2sh', key_hex[:2]) + \
                    #                network_by_value('prefix_address', key_hex[:2])
                    #     if networks:
                    #         key_format = 'address'
                    #         isprivate = False

        except (TypeError, EncodingError):
            pass
    if not key_format:
        try:
            int(key)
            if 70 < len(key) < 78:
                key_format = 'decimal'
                isprivate = True
        except (TypeError, ValueError):
            pass
    if not key_format:
        raise BKeyError("Key: %s. Unrecognised key format" % key)
    else:
        return {
            "format": key_format,
            "networks": networks,
            "isprivate": isprivate
        }