Ejemplo n.º 1
0
def list_purchases(obj):
    txs, heights = obj['txs'], obj['heights']
    o = []
    for h in txs:
        txhex = str(txs[h])
        # print txhex
        txouts = b.deserialize(txhex)['outs']
        if len(txouts) >= 2 and txouts[0]['value'] >= minimum - 30000:
            addr = b.script_to_address(txouts[0]['script'])
            if addr == exodus:
                v = txouts[0]['value'] + 30000
                ht = heights[h]
                # We care about the timestamp of the previous
                # confirmed block before a transaction
                t = get_block_header_data(ht - 1)['timestamp']
                o.append({
                    "tx": h,
                    "addr": b.b58check_to_hex(b.script_to_address(
                                              txouts[1]['script'])),
                    "value": v,
                    "time": t
                })
                if len(o) % 50 == 0:
                    sys.stderr.write('Gathered outputs: %d\n' % len(o))
    return o
Ejemplo n.º 2
0
    def add_tx_notify(self,
                      txd,
                      unconfirmfun,
                      confirmfun,
                      notifyaddr,
                      timeoutfun=None):
        if not self.notifythread:
            self.notifythread = BitcoinCoreNotifyThread(self)
            self.notifythread.start()
        one_addr_imported = False
        for outs in txd['outs']:
            addr = btc.script_to_address(outs['script'], get_p2pk_vbyte())
            if self.rpc('getaccount', [addr]) != '':
                one_addr_imported = True
                break
        if not one_addr_imported:
            self.rpc('importaddress', [notifyaddr, 'joinmarket-notify', False])
        tx_output_set = set([(sv['script'], sv['value'])
                             for sv in txd['outs']])
        self.txnotify_fun.append(
            (tx_output_set, unconfirmfun, confirmfun, timeoutfun, False))

        #create unconfirm timeout here, create confirm timeout in the other thread
        if timeoutfun:
            threading.Timer(jm_single().config.getint('TIMEOUT',
                                                      'unconfirm_timeout_sec'),
                            bitcoincore_timeout_callback,
                            args=(False, tx_output_set, self.txnotify_fun,
                                  timeoutfun)).start()
Ejemplo n.º 3
0
    def add_tx_notify(self,
                      txd,
                      unconfirmfun,
                      confirmfun,
                      notifyaddr,
                      timeoutfun=None):
        if not self.notifythread:
            self.notifythread = BitcoinCoreNotifyThread(self)
            self.notifythread.start()
        one_addr_imported = False
        for outs in txd['outs']:
            addr = btc.script_to_address(outs['script'], get_p2pk_vbyte())
            if self.rpc('getaccount', [addr]) != '':
                one_addr_imported = True
                break
        if not one_addr_imported:
            self.rpc('importaddress', [notifyaddr, 'joinmarket-notify', False])
        tx_output_set = set([(sv['script'], sv['value']) for sv in txd['outs']])
        self.txnotify_fun.append((tx_output_set, unconfirmfun, confirmfun,
                                  timeoutfun, False))

        #create unconfirm timeout here, create confirm timeout in the other thread
        if timeoutfun:
            threading.Timer(jm_single().config.getint('TIMEOUT',
                                                      'unconfirm_timeout_sec'),
                            bitcoincore_timeout_callback,
                            args=(False, tx_output_set, self.txnotify_fun,
                                  timeoutfun)).start()
Ejemplo n.º 4
0
 def on_tx_confirmed(self, cjorder, confirmations, txid):
     to_announce = []
     for i, out in enumerate(cjorder.tx['outs']):
         addr = btc.script_to_address(out['script'], get_p2pk_vbyte())
         if addr == cjorder.change_addr:
             neworder = {
                 'oid': self.get_next_oid(),
                 'ordertype': 'absorder',
                 'minsize': 12000,
                 'maxsize': out['value'],
                 'txfee': 10000,
                 'cjfee': 100000,
                 'utxo': txid + ':' + str(i)
             }
             to_announce.append(neworder)
         if addr == cjorder.cj_addr:
             neworder = {
                 'oid': self.get_next_oid(),
                 'ordertype': 'absorder',
                 'minsize': 12000,
                 'maxsize': out['value'],
                 'txfee': 10000,
                 'cjfee': 100000,
                 'utxo': txid + ':' + str(i)
             }
             to_announce.append(neworder)
     return [], to_announce
Ejemplo n.º 5
0
def takeUtxo(utxo, privs, bch_inputs, skip_if_blank=False):
    """ Take UTXO for spending and update the input arrays and private key set for later signing. """
    intxhsh = utxo.txhash
    log.info("Looking at UTXO %s.", utxo)
    if "BCH_" + intxhsh not in tokenval.db:
        log.info("Input transaction missing for UTXO %s.", utxo)
        return None, None

    intx = tokenval.db["BCH_" + intxhsh]

    bch_prevout = intx.decoded["outs"][utxo.outnum]
    bch_prevout_addr = bitcoin.script_to_address(bch_prevout["script"])
    priv = tokenval.privKey(bch_prevout_addr)

    if priv is None:
        log.info("Private key not available for unspent output %s.", utxo)
        return None, None

    log.info("Taking unspent output %s.", utxo)

    if not skip_if_blank or utxo.value is not None:
        privoutpoint = utxo.txhash + ":" + str(utxo.outnum)
        privs[privoutpoint] = priv

        bch_inputs.append({"output": privoutpoint, "amount": utxo.bch_value})

    return utxo.value, utxo.bch_value
Ejemplo n.º 6
0
def getBalances():
    """ Available (spendable) balances for all tokens. FIXME: super inefficient..."""
    addr2tokenid = {}
    for key in db:
        if key.startswith("TOKEN_"):
            rt = db[key]
            addr2tokenid[rt.addr] = rt.tokenid

    balances = {}
    outputs = allUnspentOutputs()
    for out in outputs:
        if out.token_addr not in addr2tokenid:
            continue

        tokenid = addr2tokenid[out.token_addr]

        if "BCH_" + out.txhash not in db:
            continue

        tx = db["BCH_" + out.txhash]
        spend_addr = bitcoin.script_to_address(
            tx.decoded["outs"][out.outnum]["script"])
        if privKey(spend_addr) is None:
            if tokenid not in balances:
                balances[tokenid] = 0
            continue

        value = 0 if out.value is None else out.value

        if tokenid in balances:
            balances[tokenid] += value
        else:
            balances[tokenid] = value
    return balances
def list_purchases(obj):
    txs, heights = obj['txs'], obj['heights']
    o = []
    for h in txs:
        txhex = str(txs[h])
        # print txhex
        txouts = b.deserialize(txhex)['outs']
        if len(txouts) >= 2:
            addr = b.script_to_address(txouts[0]['script'])
            if addr == exodus:
                v = txouts[0][
                    'value'] + 10000  # add 0.1 millibit for the fees paid transfering from koinify wallet to Factom multisig
                ht = heights[h]
                # We care about the timestamp of the previous
                # confirmed block before a transaction
                t = get_block_header_data(ht - 1)['timestamp']
                o.append({
                    "tx": h,
                    "addr": extract_pubkey(txouts[1]['script']),
                    "value": v,
                    "time": t
                })
                if len(o) % 50 == 0:
                    sys.stderr.write('Gathered outputs: %d\n' % len(o))
    return o
def list_purchases(obj):
    txs, heights = obj['txs'], obj['heights']
    process_queue = []
    for h in txs:
        txhex = str(txs[h])
        txouts = b.deserialize(txhex)['outs']
        if len(txouts) >= 2 and txouts[0]['value'] >= minimum - 30000:
            addr = b.script_to_address(txouts[0]['script'])
            if addr == exodus:
                v = txouts[0]['value'] + 30000
                process_queue.append({
                    "tx":
                    h,
                    "addr":
                    b.b58check_to_hex(b.script_to_address(
                        txouts[1]['script'])),
                    "value":
                    v,
                    "height":
                    heights[h]
                })
            else:
                sys.stderr.write(
                    "Non-purchase tx found (not to exodus): %s\n" % h)
        elif len(txouts) == 1:
            sys.stderr.write("Non-purchase tx found (single output): %s\n" % h)
        else:
            sys.stderr.write(
                "Non-purchase tx found (insufficient value): %s\n" % h)
    sys.stderr.write('Gathered outputs, collecting block timestamps\n')
    # Determine the timestamp for every block height. We care about
    # the timestamp of the previous confirmed block before a transaction.
    # Save the results as a dictionary of transaction data
    o = []
    for i in range(0, len(process_queue), 20):
        subpq = process_queue[i:i + 20]
        t = get_block_timestamp([x['height'] - 1 for x in subpq])
        assert len(t) == len(subpq), [x['height'] - 1 for x in subpq]
        o.extend([{
            "tx": _a["tx"],
            "addr": _a["addr"],
            "value": _a["value"],
            "time": _b
        } for _a, _b in zip(subpq, t)])
        sys.stderr.write('Collected timestamps: %d\n' % len(o))
    return o
Ejemplo n.º 9
0
 def get_pubkey_derivation(self, x_pubkey):
     if x_pubkey[0:2] in ['02', '03', '04']:
         if x_pubkey in self.keypairs.keys():
             return x_pubkey
     elif x_pubkey[0:2] == 'fd':
         addr = bitcoin.script_to_address(x_pubkey[2:])
         if addr in self.addresses:
             return self.addresses[addr].get('pubkey')
Ejemplo n.º 10
0
			def __init__(self, blockr_domain, txd, unconfirmfun, confirmfun):
				threading.Thread.__init__(self)
				self.daemon = True
				self.blockr_domain = blockr_domain
				self.unconfirmfun = unconfirmfun
				self.confirmfun = confirmfun
				self.tx_output_set = set([(sv['script'], sv['value']) for sv in txd['outs']])
				self.output_addresses = [btc.script_to_address(scrval[0],
					common.get_p2pk_vbyte()) for scrval in self.tx_output_set]
				common.debug('txoutset=' + pprint.pformat(self.tx_output_set))
				common.debug('outaddrs=' + ','.join(self.output_addresses))
Ejemplo n.º 11
0
			def __init__(self, blockr_domain, txd, unconfirmfun, confirmfun):
				threading.Thread.__init__(self)
				self.daemon = True
				self.blockr_domain = blockr_domain
				self.unconfirmfun = unconfirmfun
				self.confirmfun = confirmfun
				self.tx_output_set = set([(sv['script'], sv['value']) for sv in txd['outs']])
				self.output_addresses = [btc.script_to_address(scrval[0],
					common.get_p2pk_vbyte()) for scrval in self.tx_output_set]
				common.debug('txoutset=' + pprint.pformat(self.tx_output_set))
				common.debug('outaddrs=' + ','.join(self.output_addresses))
Ejemplo n.º 12
0
 def add_new_utxos(self, tx, txid):
     added_utxos = {}
     for index, outs in enumerate(tx["outs"]):
         addr = btc.script_to_address(outs["script"], get_addr_vbyte())
         if addr not in self.addr_cache:
             continue
         addrdict = {"address": addr, "value": outs["value"]}
         utxo = txid + ":" + str(index)
         added_utxos[utxo] = addrdict
         self.unspent[utxo] = addrdict
     debug("added utxos, wallet now is \n" + pprint.pformat(self.get_utxos_by_mixdepth()))
     return added_utxos
Ejemplo n.º 13
0
	def add_new_utxos(self, tx, txid):
		added_utxos = {}
		for index, outs in enumerate(tx['outs']):
			addr = btc.script_to_address(outs['script'], get_addr_vbyte())
			if addr not in self.addr_cache:
				continue
			addrdict = {'address': addr, 'value': outs['value']}
			utxo = txid + ':' + str(index)
			added_utxos[utxo] = addrdict
			self.unspent[utxo] = addrdict
		debug('added utxos, wallet now is \n' + pprint.pformat(self.get_utxos_by_mixdepth()))
		return added_utxos
Ejemplo n.º 14
0
	def add_new_utxos(self, tx, txid):
		added_utxos = {}
		for index, outs in enumerate(tx['outs']):
			addr = btc.script_to_address(outs['script'], get_p2pk_vbyte())
			if addr not in self.addr_cache:
				continue
			addrdict = {'address': addr, 'value': outs['value']}
			utxo = txid + ':' + str(index)
			added_utxos[utxo] = addrdict
			self.unspent[utxo] = addrdict
		debug('added utxos, wallet now is \n' + pprint.pformat(self.get_utxos_by_mixdepth()))
		return added_utxos
Ejemplo n.º 15
0
def list_purchases(obj):
    txs, heights = obj['txs'], obj['heights']
    process_queue = []
    for h in txs:
        txhex = str(txs[h])
        txouts = b.deserialize(txhex)['outs']
        if len(txouts) >= 2 and txouts[0]['value'] >= minimum - 30000:
            addr = b.script_to_address(txouts[0]['script'])
            if addr == exodus:
                v = txouts[0]['value'] + 30000
                process_queue.append({
                    "tx": h,
                    "addr": b.b58check_to_hex(b.script_to_address(
                                              txouts[1]['script'])),
                    "value": v,
                    "height": heights[h]
                })
            else:
                sys.stderr.write("Non-purchase tx found (not to exodus): %s\n" % h)
        elif len(txouts) == 1:
            sys.stderr.write("Non-purchase tx found (single output): %s\n" % h)
        else:
            sys.stderr.write("Non-purchase tx found (insufficient value): %s\n" % h)
    sys.stderr.write('Gathered outputs, collecting block timestamps\n')
    # Determine the timestamp for every block height. We care about
    # the timestamp of the previous confirmed block before a transaction.
    # Save the results as a dictionary of transaction data
    o = []
    for i in range(0, len(process_queue), 20):
        subpq = process_queue[i:i+20]
        t = get_block_timestamp([x['height'] - 1 for x in subpq])
        assert len(t) == len(subpq), [x['height'] - 1 for x in subpq]
        o.extend([{
            "tx": _a["tx"],
            "addr": _a["addr"],
            "value": _a["value"],
            "time": _b
        } for _a, _b in zip(subpq, t)])
        sys.stderr.write('Collected timestamps: %d\n' % len(o))
    return o
Ejemplo n.º 16
0
 def add_tx_notify(self, txd, unconfirmfun, confirmfun, notifyaddr):
     if not self.notifythread:
         self.notifythread = BitcoinCoreNotifyThread(self)
         self.notifythread.start()
     one_addr_imported = False
     for outs in txd['outs']:
         addr = btc.script_to_address(outs['script'], get_p2pk_vbyte())
         if self.rpc('getaccount', [addr]) != '':
             one_addr_imported = True
             break
     if not one_addr_imported:
         self.rpc('importaddress', [notifyaddr, 'joinmarket-notify', False])
     tx_output_set = set([(sv['script'], sv['value']) for sv in txd['outs']])
     self.txnotify_fun.append((tx_output_set, unconfirmfun, confirmfun))
Ejemplo n.º 17
0
	def add_tx_notify(self, txd, unconfirmfun, confirmfun, notifyaddr):
		if not self.notifythread:
			self.notifythread = BitcoinCoreNotifyThread(self)
			self.notifythread.start()
		one_addr_imported = False
		for outs in txd['outs']:
			addr = btc.script_to_address(outs['script'], common.get_p2pk_vbyte())
			if self.rpc('getaccount', [addr]) != '':
				one_addr_imported = True
				break
		if not one_addr_imported:
			self.rpc('importaddress', [notifyaddr, 'joinmarket-notify', False])
		tx_output_set = set([(sv['script'], sv['value']) for sv in txd['outs']])
		self.txnotify_fun.append((tx_output_set, unconfirmfun, confirmfun))
Ejemplo n.º 18
0
def script_hex_to_address( script_hex ):
    """
    Examine a scriptPubkey and extract an address.
    """
    if script_hex.startswith("76a914") and script_hex.endswith("88ac") and len(script_hex) == 50:
        # p2pkh script
        return pybitcoin.script_hex_to_address( script_hex, version_byte=version_byte )

    elif script_hex.startswith("a914") and script_hex.endswith("87") and len(script_hex) == 46:
        # p2sh script
        return bitcoin.script_to_address( script_hex, vbyte=multisig_version_byte )

    else:
        raise ValueError("Nonstandard script %s" % script_hex)
Ejemplo n.º 19
0
	def on_tx_confirmed(self, cjorder, confirmations, txid):
		to_announce = []
		for i, out in enumerate(cjorder.tx['outs']):
			addr = btc.script_to_address(out['script'], get_addr_vbyte())
			if addr == cjorder.change_addr:
				neworder = {'oid': self.get_next_oid(), 'ordertype': 'absorder', 'minsize': 12000,
					'maxsize': out['value'], 'txfee': 10000, 'cjfee': 100000,
					'utxo': txid + ':' + str(i)}
				to_announce.append(neworder)
			if addr == cjorder.cj_addr:
				neworder = {'oid': self.get_next_oid(), 'ordertype': 'absorder', 'minsize': 12000,
					'maxsize': out['value'], 'txfee': 10000, 'cjfee': 100000,
					'utxo': txid + ':' + str(i)}
				to_announce.append(neworder)
		return ([], to_announce)
Ejemplo n.º 20
0
    def verify_unsigned_tx(self, txd):
        tx_utxo_set = set(ins['outpoint']['hash'] + ':' + str(
                ins['outpoint']['index']) for ins in txd['ins'])
        # complete authentication: check the tx input uses the authing pubkey
        input_utxo_data = jm_single().bc_interface.query_utxo_set(
                list(tx_utxo_set))

        if None in input_utxo_data:
            return False, 'some utxos already spent or not confirmed yet'
        input_addresses = [u['address'] for u in input_utxo_data]
        if btc.pubtoaddr(
                self.i_utxo_pubkey, get_p2pk_vbyte()) not in input_addresses:
            return False, "authenticating bitcoin address is not contained"

        my_utxo_set = set(self.utxos.keys())
        if not tx_utxo_set.issuperset(my_utxo_set):
            return False, 'my utxos are not contained'

        my_total_in = sum([va['value'] for va in self.utxos.values()])
        self.real_cjfee = calc_cj_fee(
                self.ordertype, self.cjfee, self.cj_amount)
        expected_change_value = (
            my_total_in - self.cj_amount - self.txfee + self.real_cjfee)
        log.debug('potentially earned = {}'.format(
                self.real_cjfee - self.txfee))
        log.debug('mycjaddr, mychange = {}, {}'.format(
                self.cj_addr, self.change_addr))

        times_seen_cj_addr = 0
        times_seen_change_addr = 0
        for outs in txd['outs']:
            addr = btc.script_to_address(outs['script'], get_p2pk_vbyte())
            if addr == self.cj_addr:
                times_seen_cj_addr += 1
                if outs['value'] != self.cj_amount:
                    return False, 'Wrong cj_amount. I expect ' + str(
                            self.cj_amount)
            if addr == self.change_addr:
                times_seen_change_addr += 1
                if outs['value'] != expected_change_value:
                    return False, 'wrong change, i expect ' + str(
                            expected_change_value)
        if times_seen_cj_addr != 1 or times_seen_change_addr != 1:
            fmt = ('cj or change addr not in tx '
                   'outputs once, #cjaddr={}, #chaddr={}').format
            return False, (fmt(times_seen_cj_addr, times_seen_change_addr))
        return True, None
Ejemplo n.º 21
0
    def verify_unsigned_tx(self, txd):
        tx_utxo_set = set(ins['outpoint']['hash'] + ':' +
                          str(ins['outpoint']['index']) for ins in txd['ins'])
        # complete authentication: check the tx input uses the authing pubkey
        input_utxo_data = jm_single().bc_interface.query_utxo_set(
            list(tx_utxo_set))

        if None in input_utxo_data:
            return False, 'some utxos already spent or not confirmed yet'
        input_addresses = [u['address'] for u in input_utxo_data]
        if btc.pubtoaddr(self.i_utxo_pubkey,
                         get_p2pk_vbyte()) not in input_addresses:
            return False, "authenticating bitcoin address is not contained"

        my_utxo_set = set(self.utxos.keys())
        if not tx_utxo_set.issuperset(my_utxo_set):
            return False, 'my utxos are not contained'

        my_total_in = sum([va['value'] for va in self.utxos.values()])
        self.real_cjfee = calc_cj_fee(self.ordertype, self.cjfee,
                                      self.cj_amount)
        expected_change_value = (my_total_in - self.cj_amount - self.txfee +
                                 self.real_cjfee)
        log.debug('potentially earned = {}'.format(self.real_cjfee -
                                                   self.txfee))
        log.debug('mycjaddr, mychange = {}, {}'.format(self.cj_addr,
                                                       self.change_addr))

        times_seen_cj_addr = 0
        times_seen_change_addr = 0
        for outs in txd['outs']:
            addr = btc.script_to_address(outs['script'], get_p2pk_vbyte())
            if addr == self.cj_addr:
                times_seen_cj_addr += 1
                if outs['value'] != self.cj_amount:
                    return False, 'Wrong cj_amount. I expect ' + str(
                        self.cj_amount)
            if addr == self.change_addr:
                times_seen_change_addr += 1
                if outs['value'] != expected_change_value:
                    return False, 'wrong change, i expect ' + str(
                        expected_change_value)
        if times_seen_cj_addr != 1 or times_seen_change_addr != 1:
            fmt = ('cj or change addr not in tx '
                   'outputs once, #cjaddr={}, #chaddr={}').format
            return False, (fmt(times_seen_cj_addr, times_seen_change_addr))
        return True, None
Ejemplo n.º 22
0
def xpubkey_to_address(x_pubkey):
    if x_pubkey[0:2] == 'fd':
        address = bitcoin.script_to_address(x_pubkey[2:])
        return x_pubkey, address
    if x_pubkey[0:2] in ['02', '03', '04']:
        pubkey = x_pubkey
    elif x_pubkey[0:2] == 'ff':
        xpub, s = BIP32_KeyStore.parse_xpubkey(x_pubkey)
        pubkey = BIP32_KeyStore.get_pubkey_from_xpub(xpub, s)
    elif x_pubkey[0:2] == 'fe':
        mpk, s = Old_KeyStore.parse_xpubkey(x_pubkey)
        pubkey = Old_KeyStore.get_pubkey_from_mpk(mpk, s[0], s[1])
    else:
        raise BitcoinException("Cannot parse pubkey. prefix: {}".format(
            x_pubkey[0:2]))
    if pubkey:
        address = public_key_to_p2pkh(bfh(pubkey))
    return pubkey, address
Ejemplo n.º 23
0
def script_hex_address(script_hex):
    """
    Examine a scriptPubkey and extract an address
    """
    if script_hex.startswith("76a914") and script_hex.endswith("88ac") and len(
            script_hex) == 50:
        # p2pkh script
        return pybitcoin.script_hex_to_address(script_hex,
                                               version_byte=version_byte)

    elif script_hex.startswith("a914") and script_hex.endswith("87") and len(
            script_hex) == 46:
        # p2sh script
        return bitcoin.script_to_address(script_hex,
                                         vbyte=multisig_version_byte)

    else:
        raise ValueError("Nonstandard script %s" % script_hex)
Ejemplo n.º 24
0
    def verify_unsigned_tx(self, txd):
        tx_utxo_set = set([ins['outpoint']['hash'] + ':' \
                           + str(ins['outpoint']['index']) for ins in txd['ins']])
        #complete authentication: check the tx input uses the authing pubkey
        input_utxo_data = common.bc_interface.query_utxo_set(list(tx_utxo_set))
        input_addresses = [u['address'] for u in input_utxo_data]
        if btc.pubtoaddr(self.i_utxo_pubkey, get_addr_vbyte())\
         not in input_addresses:
            return False, "authenticating bitcoin address is not contained"
        my_utxo_set = set(self.utxos.keys())
        wallet_utxos = set(self.maker.wallet.unspent)
        if not tx_utxo_set.issuperset(my_utxo_set):
            return False, 'my utxos are not contained'
        if not wallet_utxos.issuperset(my_utxo_set):
            return False, 'my utxos already spent'

        my_total_in = sum([va['value'] for va in self.utxos.values()])
        self.real_cjfee = calc_cj_fee(self.ordertype, self.cjfee,
                                      self.cj_amount)
        expected_change_value = (my_total_in - self.cj_amount - self.txfee +
                                 self.real_cjfee)
        debug('earned = ' + str(self.real_cjfee - self.txfee))
        debug('mycjaddr, mychange = ' + self.cj_addr + ', ' + self.change_addr)

        times_seen_cj_addr = 0
        times_seen_change_addr = 0
        for outs in txd['outs']:
            addr = btc.script_to_address(outs['script'], get_addr_vbyte())
            if addr == self.cj_addr:
                times_seen_cj_addr += 1
                if outs['value'] != self.cj_amount:
                    return False, 'Wrong cj_amount. I expect ' + str(cj_amount)
            if addr == self.change_addr:
                times_seen_change_addr += 1
                if outs['value'] != expected_change_value:
                    return False, 'wrong change, i expect ' + str(
                        expected_change_value)
        if times_seen_cj_addr != 1 or times_seen_change_addr != 1:
            return False, (
                'cj or change addr not in tx outputs once, #cjaddr=' +
                str(times_seen_cj_addr) + ', #chaddr=' +
                str(times_seen_change_addr))
        return True, None
Ejemplo n.º 25
0
 def test_script_to_address(self):
     scripts = {
         '00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262':
         [
             'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7',
             196, False
         ],
         '00202a11fadf4a96c60669ae50b2ac7c0b3cae0b3d94483670504dc154a255826322':
         [
             'bcrt1q9ggl4h62jmrqv6dw2ze2clqt8jhqk0v5fqm8q5zdc922y4vzvv3qj3le86',
             196, True
         ],
         '00142a3af484ba735f3de4535f0fd522d4666646ef3f':
         ['bcrt1q9ga0fp96wd0nmezntu8a2gk5venydmelf8ddtm', 111, True],
         '00143262354a6825b39de7f35534ddb04f45ea7a1f43':
         ['bc1qxf3r2jngykeemeln256dmvz0gh48586rfx4j2p', 0, False]
     }
     for s, a in scripts.items():
         self.assertEqual(a[0],
                          bitcoin.script_to_address(s, a[1], regtest=a[2]))
Ejemplo n.º 26
0
def main():
    path = "blk0000"
    blockFilename = 'blk00001.dat'

    with open(blockFilename, 'rb') as blockFile:
        for block in range(0, 10):
            readBlock(blockFile)
    """len = os.stat(blockFilename).st_size
    print(len)
    with open(blockFilename, 'rb') as blockFile:
        while blockFile.tell() != len:
            readBlock(blockFile)"""

    for transaction in transactions:
        for input in inputs:
            if transaction.getHash() == input.getPreviousHash():
                for output in transaction.getOutputs():
                    print(
                        str(output.getIndex()) + " = " + str(input.getOutId()))
                    if int(output.getIndex()) == int(input.getOutId()):
                        print("TROVATO!")
                        print(transaction.toString())
                        print(input.toString() +
                              "\nhash della transazione dell'input: " +
                              input.getHashTransaction() + "\n")
                        print("\n ******** \n\n")
                        print(output.toString())
                        print(input.toString())
                        input.setHashTransaction(output.getAddress())

    with open("block01.json", "w") as outfile:
        transactionJSONData = json.dumps(transactions,
                                         indent=4,
                                         cls=TransactionEncoder)
        outfile.write(transactionJSONData)

    print(
        bitcoin.script_to_address(
            '4104c8f8fd8d4c0f56cc7b9e974c29875e893131144847ab56dcf0cb8c223f04a8e31e2ff7a7ac8626270077c2158bf0a898c2d595112e2c157b2e7177c136f7ae42ac'
        ))
Ejemplo n.º 27
0
	def verify_unsigned_tx(self, txd):
		tx_utxo_set = set([ins['outpoint']['hash'] + ':' \
		                   + str(ins['outpoint']['index']) for ins in txd['ins']])
		#complete authentication: check the tx input uses the authing pubkey
		input_utxo_data = common.bc_interface.query_utxo_set(list(tx_utxo_set))
		input_addresses = [u['address'] for u in input_utxo_data]
		if btc.pubtoaddr(self.i_utxo_pubkey, get_addr_vbyte())\
			not in input_addresses:
		        return False, "authenticating bitcoin address is not contained"
		my_utxo_set = set(self.utxos.keys())
		wallet_utxos = set(self.maker.wallet.unspent)
		if not tx_utxo_set.issuperset(my_utxo_set):
			return False, 'my utxos are not contained'
		if not wallet_utxos.issuperset(my_utxo_set):
			return False, 'my utxos already spent'

		my_total_in = sum([va['value'] for va in self.utxos.values()])
		self.real_cjfee = calc_cj_fee(self.ordertype, self.cjfee, self.cj_amount)
		expected_change_value = (my_total_in - self.cj_amount
			- self.txfee + self.real_cjfee)
		debug('earned = ' + str(self.real_cjfee - self.txfee))
		debug('mycjaddr, mychange = ' + self.cj_addr + ', ' + self.change_addr)

		times_seen_cj_addr = 0
		times_seen_change_addr = 0
		for outs in txd['outs']:
			addr = btc.script_to_address(outs['script'], get_addr_vbyte())
			if addr == self.cj_addr:
				times_seen_cj_addr += 1
				if outs['value'] != self.cj_amount:
					return False, 'Wrong cj_amount. I expect ' + str(cj_amount)
			if addr == self.change_addr:
				times_seen_change_addr += 1
				if outs['value'] != expected_change_value:
					return False, 'wrong change, i expect ' + str(expected_change_value)
		if times_seen_cj_addr != 1 or times_seen_change_addr != 1:
			return False, ('cj or change addr not in tx outputs once, #cjaddr='
				+ str(times_seen_cj_addr) + ', #chaddr=' + str(times_seen_change_addr))
		return True, None
Ejemplo n.º 28
0
    def verify_unsigned_tx(self, txd):
        tx_utxo_set = set(ins['outpoint']['hash'] + ':' + str(
                ins['outpoint']['index']) for ins in txd['ins'])

        my_utxo_set = set(self.utxos.keys())
        if not tx_utxo_set.issuperset(my_utxo_set):
            return False, 'my utxos are not contained'

        my_total_in = sum([va['value'] for va in self.utxos.values()])
        self.real_cjfee = calc_cj_fee(
                self.ordertype, self.cjfee, self.cj_amount)
        expected_change_value = (
            my_total_in - self.cj_amount - self.txfee + self.real_cjfee)
        log.info('potentially earned = {}'.format(
                self.real_cjfee - self.txfee))
        log.debug('mycjaddr, mychange = {}, {}'.format(
                self.cj_addr, self.change_addr))

        times_seen_cj_addr = 0
        times_seen_change_addr = 0
        for outs in txd['outs']:
            addr = btc.script_to_address(outs['script'], get_p2pk_vbyte())
            if addr == self.cj_addr:
                times_seen_cj_addr += 1
                if outs['value'] != self.cj_amount:
                    return False, 'Wrong cj_amount. I expect ' + str(
                            self.cj_amount)
            if addr == self.change_addr:
                times_seen_change_addr += 1
                if outs['value'] != expected_change_value:
                    return False, 'wrong change, i expect ' + str(
                            expected_change_value)
        if times_seen_cj_addr != 1 or times_seen_change_addr != 1:
            fmt = ('cj or change addr not in tx '
                   'outputs once, #cjaddr={}, #chaddr={}').format
            return False, (fmt(times_seen_cj_addr, times_seen_change_addr))
        return True, None
Ejemplo n.º 29
0
    def verify_unsigned_tx(self, txd):
        tx_utxo_set = set(ins['outpoint']['hash'] + ':' +
                          str(ins['outpoint']['index']) for ins in txd['ins'])

        my_utxo_set = set(self.utxos.keys())
        if not tx_utxo_set.issuperset(my_utxo_set):
            return False, 'my utxos are not contained'

        my_total_in = sum([va['value'] for va in self.utxos.values()])
        self.real_cjfee = calc_cj_fee(self.ordertype, self.cjfee,
                                      self.cj_amount)
        expected_change_value = (my_total_in - self.cj_amount - self.txfee +
                                 self.real_cjfee)
        log.debug('potentially earned = {}'.format(self.real_cjfee -
                                                   self.txfee))
        log.debug('mycjaddr, mychange = {}, {}'.format(self.cj_addr,
                                                       self.change_addr))

        times_seen_cj_addr = 0
        times_seen_change_addr = 0
        for outs in txd['outs']:
            addr = btc.script_to_address(outs['script'], get_p2pk_vbyte())
            if addr == self.cj_addr:
                times_seen_cj_addr += 1
                if outs['value'] != self.cj_amount:
                    return False, 'Wrong cj_amount. I expect ' + str(
                        self.cj_amount)
            if addr == self.change_addr:
                times_seen_change_addr += 1
                if outs['value'] != expected_change_value:
                    return False, 'wrong change, i expect ' + str(
                        expected_change_value)
        if times_seen_cj_addr != 1 or times_seen_change_addr != 1:
            fmt = ('cj or change addr not in tx '
                   'outputs once, #cjaddr={}, #chaddr={}').format
            return False, (fmt(times_seen_cj_addr, times_seen_change_addr))
        return True, None
def list_purchases(obj):
    txs, heights = obj['txs'], obj['heights']
    o = []
    for h in txs:
        txhex = str(txs[h])
        # print txhex
        txouts = b.deserialize(txhex)['outs']
        if len(txouts) >= 2:
            addr = b.script_to_address(txouts[0]['script'])
            if addr == exodus:
                v = txouts[0]['value'] + 10000  # add 0.1 millibit for the fees paid transfering from koinify wallet to Factom multisig
                ht = heights[h]
                # We care about the timestamp of the previous
                # confirmed block before a transaction
                t = get_block_header_data(ht - 1)['timestamp']
                o.append({
                    "tx": h,
                    "addr": extract_pubkey(txouts[1]['script']),
                    "value": v,
                    "time": t
                })
                if len(o) % 50 == 0:
                    sys.stderr.write('Gathered outputs: %d\n' % len(o))
    return o
Ejemplo n.º 31
0
def validate(recovery_package):
    package_out = 0
    total_out = 0
    total_in = 0
    total_fee = 0
    raw_txs = recovery_package['txs']
    print "Validating %d transactions" % len(raw_txs)
    for tx_index, tx_raw in enumerate(raw_txs):
        print "\nTransaction #", tx_index
        tx = bitcoin.transaction.deserialize(unhexlify(tx_raw['bytes']))
        tx_out = 0
        tx_in = 0
        tx_fee = 0
        for inp in tx['ins']:
            tx_hash = inp['outpoint']['hash']
            vout = inp['outpoint']['index']
            print "\tInput", hexlify(tx_hash) + ":" + str(vout)
            try:
                intx_hex = bitcoin.fetchtx(tx_hash)
                intx = bitcoin.transaction.deserialize(unhexlify(intx_hex))
                prev_out = intx['outs'][vout]
                print "\t  paying " + value_print(
                    prev_out['value']), "to", bitcoin.script_to_address(
                        prev_out['script'])
                tx_in += prev_out['value']
            except:
                print "Exception in input retrieval - skipping online validation"
                pass

        for outp in tx['outs']:
            print "\tOutput paying " + value_print(
                outp['value']), "to", bitcoin.script_to_address(outp['script'])
            tx_out += outp['value']
        print "\n-------------------------------"
        if tx_in > 0:
            print "- Total in " + value_print(tx_in)
            total_in += tx_in
        print "- Total out" + value_print(tx_out)
        total_out += tx_out
        if total_in > 0:
            tx_fee = tx_in - tx_out
            total_fee += tx_fee
            print "- Total fee" + value_print(tx_fee)
            tx_size = len(tx_raw['bytes']) / 4
            feePerByte = tx_fee / tx_size
            print "- Tx size", tx_size, "bytes"
            print "- Fee per byte", feePerByte, "satoshi"
            if feePerByte > 100:
                print "WARNING - Excessive fee per byte", feePerByte
            if total_fee > 150000:
                print "WARNING - Unusually large fee", value_print(total_fee)
            if total_fee > (total_out / 100):
                raise Exception("ERROR - Fee exceeds 1% of Tx" +
                                value_print(total_fee))

    # check total outputs match expected amount
    print "\n\n=================================================="
    if total_in > 0:
        print "Total inputs for all transactions", value_print(total_in)
    print "Total outputs for all transactions", value_print(total_out)
    if total_in > 0:
        print "Total fees for all transactions", value_print(total_fee)

    if total_out == recovery_package['header']['total_out']:
        print "\n\nTotal outputs for all transactions match the recovery package header"
    else:
        raise Exception(
            "Total outputs for all transactions do not match the recovery package header"
        )
Ejemplo n.º 32
0
def processOnchain(txn):
    if txn.handle in db:
        log.warning("Have seen and processed on chain transaction %s already.",
                    txn.handle)
        return

    # find and extract OP_RETURN data if available
    opreturn_data = None
    for output in txn.decoded["outs"]:
        assert ("script" in output)
        if output["script"].startswith("6a"):  # OP_RETURN?
            opreturn_data = output["script"][4:]  # skip length byte

    if opreturn_data is None:
        # transactions without OP_RETURN data are of interest for
        # their BCH outputs (to fill up miner fees)
        # and the potential tokens that can be created from these outputs.

        log.info(
            "Assuming transaction %s is generating transaction or meant for extra BCH fee input",
            txn.handle)
        for n, output in enumerate(txn.decoded["outs"]):
            script = output["script"]
            out_addr = bitcoin.script_to_address(script)
            log.info("Generating unspent blank output %s:%s:%d:%d", out_addr,
                     txn.hsh, n, output["value"])
            key = "UNSPENT_" + txn.hsh + ("_%d" % n)
            if key in db:
                log.error("Internal error, outpoint already in DB.")
                return
            db[key] = UnspentOutput(out_addr, txn.hsh, n, output["value"],
                                    None)
        # ok, transaction is coming in order, add to DB and be done
        db[txn.handle] = txn
        return

    if len(opreturn_data) != 64:
        # a single SHA256 hash is expected
        log.error("Transaction %s does not contain valid OP_RETURN data.",
                  txn.handle)
        return

    tok_handle = "TOK_" + opreturn_data  # handle to look for in DB
    if tok_handle not in db:
        log.error(
            "Transaction %s contains unknown OP_RETURN data. Please import token transaction first.",
            txn.handle)
        return

    toktxn = db[tok_handle]

    # check that the addresses for the signatures on the token transaction matching the signatures for the inputs of
    # the BCH transaction
    tok_addrs = set(toktxn.signed_addresses)

    bch_addrs = set()
    for inp in txn.decoded["ins"]:
        point = inp["outpoint"]
        txhsh, outnum = point["hash"], point["index"]

        if "BCH_" + txhsh not in db:
            log.error("Missing BCH transaction input %s:%d.", txhsh, outnum)
            return
        else:
            out = db["BCH_" + txhsh].decoded["outs"][outnum]
            addr = bitcoin.script_to_address(out["script"])
            bch_addrs.add(addr)

    if tok_addrs != bch_addrs:
        log.error(
            "Signatures for BCH transaction %s mismatch those for the token transaction %s.",
            txn.handle, toktxn.handle)
        log.error("Signed addresses for token transaction: %s",
                  repr(tok_addrs))
        log.error("Signed addresses for BCH transaction: %s", repr(bch_addrs))
        return

    if len(toktxn.outputs) != len(txn.decoded["outs"]) - 1:
        log.error(
            "Token transaction needs to have the same number of outputs as the BCH transaction minus one (for OP_RETURN)."
        )
        log.error("Token outputs: %s", repr(toktxn.outputs))
        log.error("BCH outputs: %s", repr(txn.decoded["outs"]))
        return

    # calculate input values, taking minted tokens with CREATE into account
    valuesum = 0
    for mint in toktxn.mints:
        chainprevtxid, chainprevout, value = mint
        key = "UNSPENT_" + chainprevtxid + ("_%d" % chainprevout)

        if key not in db:
            log.error("Unspent output %s:%d referenced in create not in DB.\n",
                      chainprevtxid, chainprevout)
            return

        utxo = db[key]
        if utxo.value is not None:
            log.error(
                "Trying to create a token from non-blank output %s:%d.\n",
                chainprevtxid, chainprevout)
            return

        if utxo.token_addr != toktxn.token_addr:
            log.error(
                "Trying to create a token from blank output with wrong address %s:%d\n",
                chainprevtxid, chainprevout)
            return

        if value < 0:
            log.error("Trying to create negative number of tokens.\n")
            return
        valuesum += value
        log.info("Adding mint value %d, total %d", value, valuesum)

    for inp in txn.decoded["ins"]:
        txid = inp["outpoint"]["hash"]
        outnum = inp["outpoint"]["index"]

        key = "UNSPENT_" + txid + ("_%d" % outnum)
        if key not in db:
            log.error("Missing unspent output %s:%d.", txid, outnum)
            return

        utxo = db[key]

        if utxo.value is not None:
            if utxo.token_addr != toktxn.token_addr:
                log.error("Input token address mismatch %s vs. %s.",
                          utxo.token_addr, toktxn.token_addr)
                return

            valuesum += utxo.value
            log.info("Adding input value %d, total %d", utxo.value, valuesum)

    for value in toktxn.outputs:
        valuesum -= value
        log.info("Subtracting output value %d, total %d", value, valuesum)

    if valuesum < 0:
        log.error("Transaction %s trying to overspend.", toktxn.handle)
        return

    for value in toktxn.outputs:
        if value < 0:
            log.error("Trying to create negative output")
            return

    # consume inputs,
    for inp in txn.decoded["ins"]:
        txid = inp["outpoint"]["hash"]
        outnum = inp["outpoint"]["index"]

        key = "UNSPENT_" + txid + ("_%d" % outnum)
        del db[key]

    # create outputs
    for n, value in enumerate(toktxn.outputs):
        key = "UNSPENT_" + txn.hsh + ("_%d" % n)
        if key in db:
            log.error("Internal error, output exists.")
            return

        out = txn.decoded["outs"][n]
        script = out["script"]
        addr = bitcoin.script_to_address(script)
        if value > 0:
            db[key] = UnspentOutput(toktxn.token_addr, txn.hsh, n,
                                    out["value"], value)
        else:
            db[key] = UnspentOutput(addr, txn.hsh, n, out["value"], None)

    # and put onchain txn into DB
    db[txn.handle] = txn
Ejemplo n.º 33
0
def script_to_address(script):
    #TODO bech32 addresses
    #TODO testnet, although everything uses scripthash so the address vbyte doesnt matter
    return btc.script_to_address(script, 0x00)
Ejemplo n.º 34
0
    field_names = ['tx#', 'timestamp', 'type', 'amount/btc',
        'balance-change/btc', 'balance/btc', 'coinjoin-n', 'total-fees',
        'utxo-count', 'mixdepth-from', 'mixdepth-to']
    if options.csv:
        field_names += ['txid']
    l = s().join(field_names)
    print(l)
    balance = 0
    utxo_count = 0
    deposits = []
    deposit_times = []
    for i, tx in enumerate(txes):
        rpctx = jm_single().bc_interface.rpc('gettransaction', [tx['txid']])
        txhex = str(rpctx['hex'])
        txd = btc.deserialize(txhex)
        output_addr_values = dict(((btc.script_to_address(sv['script'],
            get_p2pk_vbyte()), sv['value']) for sv in txd['outs']))
        our_output_addrs = wallet_addr_set.intersection(
            output_addr_values.keys())

        from collections import Counter
        value_freq_list = sorted(Counter(output_addr_values.values())
            .most_common(), key=lambda x: -x[1])
        non_cj_freq = 0 if len(value_freq_list)==1 else sum(zip(
            *value_freq_list[1:])[1])
        is_coinjoin = (value_freq_list[0][1] > 1 and value_freq_list[0][1] in
            [non_cj_freq, non_cj_freq+1])
        cj_amount = value_freq_list[0][0]
        cj_n = value_freq_list[0][1]

        rpc_inputs = []
        for ins in txd['ins']:
Ejemplo n.º 35
0
        'mixdepth-from', 'mixdepth-to'
    ]
    if options.csv:
        field_names += ['txid']
    l = s().join(field_names)
    print(l)
    balance = 0
    utxo_count = 0
    deposits = []
    deposit_times = []
    for i, tx in enumerate(txes):
        rpctx = jm_single().bc_interface.rpc('gettransaction', [tx['txid']])
        txhex = str(rpctx['hex'])
        txd = btc.deserialize(txhex)
        output_addr_values = dict(
            ((btc.script_to_address(sv['script'],
                                    get_p2pk_vbyte()), sv['value'])
             for sv in txd['outs']))
        our_output_addrs = wallet_addr_set.intersection(
            output_addr_values.keys())

        from collections import Counter
        value_freq_list = sorted(Counter(
            output_addr_values.values()).most_common(),
                                 key=lambda x: -x[1])
        non_cj_freq = 0 if len(value_freq_list) == 1 else sum(
            zip(*value_freq_list[1:])[1])
        is_coinjoin = (value_freq_list[0][1] > 1 and value_freq_list[0][1]
                       in [non_cj_freq, non_cj_freq + 1])
        cj_amount = value_freq_list[0][0]
        cj_n = value_freq_list[0][1]