Beispiel #1
0
 def query_utxo_set(self, txout):
     if not isinstance(txout, list):
         txout = [txout]
     txids = [h[:64] for h in txout]
     txids = list(set(txids))  # remove duplicates
     # self.BLOCKR_MAX_ADDR_REQ_COUNT = 2
     if len(txids) > self.BLOCKR_MAX_ADDR_REQ_COUNT:
         txids = chunks(txids, self.BLOCKR_MAX_ADDR_REQ_COUNT)
     else:
         txids = [txids]
     data = []
     for ids in txids:
         blockr_url = 'https://' + self.blockr_domain + '.blockr.io/api/v1/tx/info/'
         blockr_data = json.loads(
                 btc.make_request(blockr_url + ','.join(ids)))['data']
         if not isinstance(blockr_data, list):
             blockr_data = [blockr_data]
         data += blockr_data
     result = []
     for txo in txout:
         txdata = [d for d in data if d['tx'] == txo[:64]][0]
         vout = [v for v in txdata['vouts'] if v['n'] == int(txo[65:])][0]
         if vout['is_spent'] == 1:
             result.append(None)
         else:
             result.append({'value': int(Decimal(vout['amount']) * Decimal(
                     '1e8')),
                            'address': vout['address'],
                            'script': vout['extras']['script']})
     return result
Beispiel #2
0
    def sync_addresses(self, wallet):
        log.debug('downloading wallet history')
        # sets Wallet internal indexes to be at the next unused address
        for mix_depth in range(wallet.max_mix_depth):
            for forchange in [0, 1]:
                unused_addr_count = 0
                last_used_addr = ''
                while (unused_addr_count < wallet.gaplimit or
                           not is_index_ahead_of_cache(
                                   wallet, mix_depth, forchange)):
                    addrs = [wallet.get_new_addr(mix_depth, forchange)
                             for _ in range(self.BLOCKR_MAX_ADDR_REQ_COUNT)]

                    # TODO send a pull request to pybitcointools
                    # because this surely should be possible with a function from it
                    blockr_url = 'https://' + self.blockr_domain
                    blockr_url += '.blockr.io/api/v1/address/txs/'

                    res = btc.make_request(blockr_url + ','.join(addrs))
                    data = json.loads(res)['data']
                    for dat in data:
                        if dat['nb_txs'] != 0:
                            last_used_addr = dat['address']
                            unused_addr_count = 0
                        else:
                            unused_addr_count += 1
                if last_used_addr == '':
                    wallet.index[mix_depth][forchange] = 0
                else:
                    wallet.index[mix_depth][forchange] = wallet.addr_cache[
                                                             last_used_addr][
                                                             2] + 1
Beispiel #3
0
    def estimate_fee_per_kb(self, N):
        bcypher_fee_estimate_url = 'https://api.blockcypher.com/v1/btc/main'
        bcypher_data = json.loads(btc.make_request(bcypher_fee_estimate_url))
        log.debug("Got blockcypher result: "+pprint.pformat(bcypher_data))
	if N<=2:
	    fee_per_kb = bcypher_data["high_fee_per_kb"]
	elif N <=4:
	    fee_per_kb = bcypher_data["medium_fee_per_kb"]
	else:
	    fee_per_kb = bcypher_data["low_fee_per_kb"]
	    
	return fee_per_kb
Beispiel #4
0
    def sync_unspent(self, wallet):
        # finds utxos in the wallet
        st = time.time()
        # dont refresh unspent dict more often than 10 minutes
        rate_limit_time = 10 * 60
        if st - self.last_sync_unspent < rate_limit_time:
            log.debug(
                    'blockr sync_unspent() happened too recently (%dsec), skipping'
                    % (st - self.last_sync_unspent))
            return
        wallet.unspent = {}

        addrs = wallet.addr_cache.keys()
        if len(addrs) == 0:
            log.debug('no tx used')
            return
        i = 0
        while i < len(addrs):
            inc = min(len(addrs) - i, self.BLOCKR_MAX_ADDR_REQ_COUNT)
            req = addrs[i:i + inc]
            i += inc

            # TODO send a pull request to pybitcointools
            # unspent() doesnt tell you which address, you get a bunch of utxos
            # but dont know which privkey to sign with

            blockr_url = 'https://' + self.blockr_domain + \
                         '.blockr.io/api/v1/address/unspent/'
            res = btc.make_request(blockr_url + ','.join(req))
            data = json.loads(res)['data']
            if 'unspent' in data:
                data = [data]
            for dat in data:
                for u in dat['unspent']:
                    wallet.unspent[u['tx'] + ':' + str(u['n'])] = {
                        'address': dat['address'],
                        'value': int(u['amount'].replace('.', ''))}
        for u in wallet.spent_utxos:
            wallet.unspent.pop(u, None)

        self.last_sync_unspent = time.time()
        log.debug('blockr sync_unspent took ' + str((self.last_sync_unspent -
                                                     st)) + 'sec')
Beispiel #5
0
            def run(self):
                st = int(time.time())
                unconfirmed_txid = None
                unconfirmed_txhex = None
                while not unconfirmed_txid:
                    time.sleep(unconfirm_poll_period)
                    if int(time.time()) - st > unconfirm_timeout:
                        log.debug('checking for unconfirmed tx timed out')
                        if self.timeoutfun:
                            self.timeoutfun(False)
                        return
                    blockr_url = 'https://' + self.blockr_domain
                    blockr_url += '.blockr.io/api/v1/address/unspent/'
                    random.shuffle(self.output_addresses
                                   )  # seriously weird bug with blockr.io
                    data = json.loads(
                            btc.make_request(blockr_url + ','.join(
                                    self.output_addresses
                            ) + '?unconfirmed=1'))['data']

                    shared_txid = None
                    for unspent_list in data:
                        txs = set([str(txdata['tx'])
                                   for txdata in unspent_list['unspent']])
                        if not shared_txid:
                            shared_txid = txs
                        else:
                            shared_txid = shared_txid.intersection(txs)
                    log.debug('sharedtxid = ' + str(shared_txid))
                    if len(shared_txid) == 0:
                        continue
                    time.sleep(
                            2
                    )  # here for some race condition bullshit with blockr.io
                    blockr_url = 'https://' + self.blockr_domain
                    blockr_url += '.blockr.io/api/v1/tx/raw/'
                    data = json.loads(btc.make_request(blockr_url + ','.join(
                            shared_txid)))['data']
                    if not isinstance(data, list):
                        data = [data]
                    for txinfo in data:
                        txhex = str(txinfo['tx']['hex'])
                        outs = set([(sv['script'], sv['value'])
                                    for sv in btc.deserialize(txhex)['outs']])
                        log.debug('unconfirm query outs = ' + str(outs))
                        if outs == self.tx_output_set:
                            unconfirmed_txid = txinfo['tx']['txid']
                            unconfirmed_txhex = str(txinfo['tx']['hex'])
                            break

                self.unconfirmfun(
                        btc.deserialize(unconfirmed_txhex), unconfirmed_txid)

                st = int(time.time())
                confirmed_txid = None
                confirmed_txhex = None
                while not confirmed_txid:
                    time.sleep(confirm_poll_period)
                    if int(time.time()) - st > confirm_timeout:
                        log.debug('checking for confirmed tx timed out')
                        if self.timeoutfun:
                            self.timeoutfun(True)
                        return
                    blockr_url = 'https://' + self.blockr_domain
                    blockr_url += '.blockr.io/api/v1/address/txs/'
                    data = json.loads(btc.make_request(blockr_url + ','.join(
                            self.output_addresses)))['data']
                    shared_txid = None
                    for addrtxs in data:
                        txs = set(str(txdata['tx'])
                                  for txdata in addrtxs['txs'])
                        if not shared_txid:
                            shared_txid = txs
                        else:
                            shared_txid = shared_txid.intersection(txs)
                    log.debug('sharedtxid = ' + str(shared_txid))
                    if len(shared_txid) == 0:
                        continue
                    blockr_url = 'https://' + self.blockr_domain
                    blockr_url += '.blockr.io/api/v1/tx/raw/'
                    data = json.loads(
                            btc.make_request(
                                    blockr_url + ','.join(shared_txid)))['data']
                    if not isinstance(data, list):
                        data = [data]
                    for txinfo in data:
                        txhex = str(txinfo['tx']['hex'])
                        outs = set([(sv['script'], sv['value'])
                                    for sv in btc.deserialize(txhex)['outs']])
                        log.debug('confirm query outs = ' + str(outs))
                        if outs == self.tx_output_set:
                            confirmed_txid = txinfo['tx']['txid']
                            confirmed_txhex = str(txinfo['tx']['hex'])
                            break
                self.confirmfun(
                        btc.deserialize(confirmed_txhex), confirmed_txid, 1)