def sync_addresses(self, wallet):
		common.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\
						wallet.index[mix_depth][forchange] <= wallet.index_cache[mix_depth][forchange]:
					addrs = [wallet.get_new_addr(mix_depth, forchange) for i 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 = 'http://' + self.blockr_domain + '.blockr.io/api/v1/address/txs/'
					#print 'downloading, lastusedaddr = ' + last_used_addr + ' unusedaddrcount= ' + str(unused_addr_count)
					res = btc.make_request(blockr_url+','.join(addrs))
					data = json.loads(res)['data']
					for dat in data:
						#if forchange == 0:
						#	print ' nbtxs ' + str(dat['nb_txs']) + ' addr=' + dat['address'] + ' unused=' + str(unused_addr_count)
						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
 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 = common.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
    def sync_addresses(self, wallet):
        common.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 i 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.io/api/v1/address/txs/'
                    #print 'downloading, lastusedaddr = ' + last_used_addr + ' unusedaddrcount= ' + str(unused_addr_count)
                    res = btc.make_request(blockr_url + ','.join(addrs))
                    data = json.loads(res)['data']
                    for dat in data:
                        #if forchange == 0:
                        #	print ' nbtxs ' + str(dat['nb_txs']) + ' addr=' + dat['address'] + ' unused=' + str(unused_addr_count)
                        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
 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
    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:
                    next_avail_idx = max([wallet.addr_cache[last_used_addr][
                        2] + 1, wallet.index_cache[mix_depth][forchange]])
                    wallet.index[mix_depth][forchange] = next_avail_idx
Exemple #6
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
    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
Exemple #8
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')
    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')
            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:
                        common.debug('checking for unconfirmed tx timed out')
                        return
                    blockr_url = 'https://' + self.blockr_domain + '.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)
                    common.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.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']])
                        common.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:
                        common.debug('checking for confirmed tx timed out')
                        return
                    blockr_url = 'https://' + self.blockr_domain + '.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)
                    common.debug('sharedtxid = ' + str(shared_txid))
                    if len(shared_txid) == 0:
                        continue
                    blockr_url = 'https://' + self.blockr_domain + '.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']])
                        common.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)
            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')
                        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')
                        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)
Exemple #12
0
def test_blockr_bad_request():
    with pytest.raises(Exception) as e_info:
        btc.make_request(blockr_root_url + "address/txs/", "0000")
Exemple #13
0
def test_blockr_bad_request():
    with pytest.raises(Exception) as e_info:
        btc.make_request(blockr_root_url+"address/txs/", "0000")