Example #1
0
    def broadcast_tx(self, tx):
        """
        Send the tx to half our peers, wait for half of the remainder to announce the tx before
        calling back True.
        """
        def on_peer_anncounce(txid):
            self.pending_txs[txid][0] += 1
            if self.pending_txs[txid][0] >= self.pending_txs[txid][1] / 2:
                if self.pending_txs[txid][3].active():
                    self.pending_txs[txid][3].cancel()
                    self.pending_txs[txid][2].callback(True)

        d = defer.Deferred()
        self.inventory[bitcoin.txhash(tx)] = tx
        inv_packet = inv("TX", bitcoin.txhash(tx))
        self.bloom_filter.insert(bitcoin.bin_txhash(tx))
        self.pending_txs[bitcoin.txhash(tx)] = [
            0,
            len(self.peers) / 2, d,
            reactor.callLater(10, d.callback, False)
        ]
        for peer in self.peers[len(self.peers) / 2:]:
            peer.protocol.update_filter()
            peer.protocol.add_inv_callback(bitcoin.txhash(tx),
                                           on_peer_anncounce)
        for peer in self.peers[:len(self.peers) / 2]:
            peer.protocol.send_message(message(inv_packet, self.params))
        return d
Example #2
0
def segwit_txhash(tx):
    if isinstance(tx, str) and re.match('^[0-9a-fA-F]*$', tx):
        tx = changebase(tx, 16, 256)
    tx_hash = txhash(tx)
    tx = strip_witness_data(tx)
    tx_id = txhash(tx)
    return {'hash': tx_hash, 'txid': tx_id}
Example #3
0
def segwit_txhash(tx):
    if isinstance(tx, str) and re.match('^[0-9a-fA-F]*$', tx):
        tx = changebase(tx, 16, 256)
    tx_hash = txhash(tx)
    tx = strip_witness_data(tx)
    tx_id = txhash(tx)
    return {'hash': tx_hash, 'txid': tx_id}
Example #4
0
 def push(self, txd):
     tx = btc.serialize(txd)
     log.debug('\n' + tx)
     log.debug('txid = ' + btc.txhash(tx))
     # TODO send to a random maker or push myself
     # TODO need to check whether the other party sent it
     # self.msgchan.push_tx(self.active_orders.keys()[0], txhex)
     pushed = jm_single().bc_interface.pushtx(tx)
     if pushed[0]:
         self.txid = btc.txhash(tx)
     else:
         log.debug('unable to pushtx, reason: '+str(pushed[1]))
     return pushed[0]
Example #5
0
    def push(self):
        tx = btc.serialize(self.latest_tx)
        log.debug('\n' + tx)
        self.txid = btc.txhash(tx)
        log.debug('txid = ' + self.txid)

        tx_broadcast = jm_single().config.get('POLICY', 'tx_broadcast')
        if tx_broadcast == 'self':
            pushed = jm_single().bc_interface.pushtx(tx)
        elif tx_broadcast in ['random-peer', 'not-self']:
            n = len(self.active_orders)
            if tx_broadcast == 'random-peer':
                i = random.randrange(n + 1)
            else:
                i = random.randrange(n)
            if i == n:
                pushed = jm_single().bc_interface.pushtx(tx)
            else:
                self.msgchan.push_tx(self.active_orders.keys()[i], tx)
                pushed = True
        elif tx_broadcast == 'random-maker':
            crow = self.db.execute(
                'SELECT DISTINCT counterparty FROM orderbook ORDER BY ' +
                'RANDOM() LIMIT 1;').fetchone()
            counterparty = crow['counterparty']
            log.debug('pushing tx to ' + counterparty)
            self.msgchan.push_tx(counterparty, tx)
            pushed = True

        if not pushed:
            log.debug('unable to pushtx')
        return pushed
Example #6
0
def make_sign_and_push(ins_full,
                       wallet,
                       amount,
                       output_addr=None,
                       change_addr=None,
                       hashcode=btc.SIGHASH_ALL):
    total = sum(x['value'] for x in ins_full.values())
    ins = ins_full.keys()
    #random output address and change addr
    output_addr = wallet.get_new_addr(1, 1) if not output_addr else output_addr
    change_addr = wallet.get_new_addr(1, 0) if not change_addr else change_addr
    outs = [{'value': amount,
             'address': output_addr}, {'value': total - amount - 100000,
                                       'address': change_addr}]

    tx = btc.mktx(ins, outs)
    de_tx = btc.deserialize(tx)
    for index, ins in enumerate(de_tx['ins']):
        utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index'])
        addr = ins_full[utxo]['address']
        priv = wallet.get_key_from_addr(addr)
        if index % 2:
            priv = binascii.unhexlify(priv)
        tx = btc.sign(tx, index, priv, hashcode=hashcode)
    #pushtx returns False on any error
    print btc.deserialize(tx)
    push_succeed = jm_single().bc_interface.pushtx(tx)
    if push_succeed:
        return btc.txhash(tx)
    else:
        return False
Example #7
0
    def push(self):
        tx = btc.serialize(self.latest_tx)
        log.debug('\n' + tx)
        self.txid = btc.txhash(tx)
        log.debug('txid = ' + self.txid)
        
        tx_broadcast = jm_single().config.get('POLICY', 'tx_broadcast')
        if tx_broadcast == 'self':
            pushed = jm_single().bc_interface.pushtx(tx)
        elif tx_broadcast in ['random-peer', 'not-self']:
            n = len(self.active_orders)
            if tx_broadcast == 'random-peer':
                i = random.randrange(n + 1)
            else:
                i = random.randrange(n)
            if i == n:
                pushed = jm_single().bc_interface.pushtx(tx)
            else:
                self.msgchan.push_tx(self.active_orders.keys()[i], tx)
                pushed = True
        elif tx_broadcast == 'random-maker':
            crow = self.db.execute(
                'SELECT DISTINCT counterparty FROM orderbook ORDER BY ' +
                'RANDOM() LIMIT 1;'
            ).fetchone()
            counterparty = crow['counterparty']
            log.debug('pushing tx to ' + counterparty)
            self.msgchan.push_tx(counterparty, tx)
            pushed = True

        if not pushed:
            log.debug('unable to pushtx')
        return pushed
Example #8
0
	def pushPayment(self):
		#compliantScript = bitcoin.mk_multisig_script([bitcoin.privtopub(self.privS), self.pubKeyClient], 2,2)  # inversion!!!!
		compliantScript = bitcoin.mk_multisig_script([self.pubKeyClient, bitcoin.privtopub(self.privS)], 2,2)
		sigServer = bitcoin.multisign(self.lastpayment, 0, compliantScript, self.privS)
		signedPtx = bitcoin.apply_multisignatures(self.lastpayment, 0, compliantScript, [self.lastsig, sigServer])
		print 'Broadcast the very last payment. Just got richer. Tx hash:', bitcoin.txhash(signedPtx)
		bitcoin.pushtx(signedPtx)
Example #9
0
def make_sign_and_push(
    ins_full, wallet, amount, output_addr=None, change_addr=None, hashcode=btc.SIGHASH_ALL, estimate_fee=False
):
    """Utility function for easily building transactions
    from wallets
    """
    total = sum(x["value"] for x in ins_full.values())
    ins = ins_full.keys()
    # random output address and change addr
    output_addr = wallet.get_new_addr(1, 1) if not output_addr else output_addr
    change_addr = wallet.get_new_addr(1, 0) if not change_addr else change_addr
    fee_est = estimate_tx_fee(len(ins), 2) if estimate_fee else 10000
    outs = [{"value": amount, "address": output_addr}, {"value": total - amount - fee_est, "address": change_addr}]

    tx = btc.mktx(ins, outs)
    de_tx = btc.deserialize(tx)
    for index, ins in enumerate(de_tx["ins"]):
        utxo = ins["outpoint"]["hash"] + ":" + str(ins["outpoint"]["index"])
        addr = ins_full[utxo]["address"]
        priv = wallet.get_key_from_addr(addr)
        if index % 2:
            priv = binascii.unhexlify(priv)
        tx = btc.sign(tx, index, priv, hashcode=hashcode)
    # pushtx returns False on any error
    print btc.deserialize(tx)
    push_succeed = jm_single().bc_interface.pushtx(tx)
    if push_succeed:
        return btc.txhash(tx)
    else:
        return False
Example #10
0
 def on_fetch(ec, result):
     if ec:
         # if it's not in the blockchain, let's try broadcasting it.
         self.log.info("Broadcasting payout tx %s to network" % bitcoin.txhash(tx))
         self.blockchain.broadcast(tx, cb=on_broadcast_complete)
     else:
         d.callback(order_id)
Example #11
0
            def on_validate(success):
                def on_fetch(ec, result):
                    if ec:
                        # if it's not in the blockchain, let's try broadcasting it.
                        self.log.info("Broadcasting payout tx %s to network" % bitcoin.txhash(tx))
                        self.blockchain.broadcast(tx, cb=on_broadcast_complete)
                    else:
                        d.callback(order_id)

                if success:
                    # broadcast anyway but don't wait for callback
                    self.log.info("Broadcasting payout tx %s to network" % bitcoin.txhash(tx))
                    self.blockchain.broadcast(tx)
                    d.callback(order_id)
                else:
                    # check to see if the tx is already in the blockchain
                    self.blockchain.fetch_transaction(unhexlify(bitcoin.txhash(tx)), on_fetch)
Example #12
0
 def on_push_tx(self, nick, txhex):
     log.debug('received txhex from ' + nick + ' to push\n' + txhex)
     pushed = jm_single().bc_interface.pushtx(txhex)
     if pushed:
         log.debug('pushed tx ' + btc.txhash(txhex))
     else:
         log.debug('failed to push tx sent by taker')
         self.msgchan.send_error(nick, 'Unable to push tx')
Example #13
0
 def on_fetch(ec, result):
     if ec:
         # if it's not in the blockchain, let's try broadcasting it.
         self.log.info("Broadcasting payout tx %s to network" %
                       bitcoin.txhash(tx))
         self.blockchain.broadcast(tx, cb=on_broadcast_complete)
     else:
         d.callback(order_id)
Example #14
0
 def on_push_tx(self, nick, txhex):
     log.debug('received txhex from ' + nick + ' to push\n' + txhex)
     pushed = jm_single().bc_interface.pushtx(txhex)
     if pushed:
         log.debug('pushed tx ' + btc.txhash(txhex))
     else:
         log.debug('failed to push tx sent by taker')
         self.msgchan.send_error(nick, 'Unable to push tx')
 def push_tx(self, tx_signed, raw=False):
     # push transactions requires a post to blockr
     path = '/tx/push'
     url = self._url + path
     payload = {'hex': tx_signed}
     response = requests.post(url, data=payload)
     if raw:
         return response
     return bitcoin.txhash(tx_signed)
Example #16
0
 def on_peer_announce(tx):
     txhash = bitcoin.txhash(bitcoin.serialize(tx["tx"]))
     if txhash in self.subscriptions[address][0] and self.subscriptions[address][0][txhash][0] != "complete":
         self.subscriptions[address][0][txhash][0] += 1
         if self.subscriptions[address][0][txhash][0] >= self.subscriptions[address][0][txhash][1]:
             self.subscriptions[address][0][txhash][0] = "complete"
             self.subscriptions[address][1](tx["tx"])
     elif txhash not in self.subscriptions[address][0]:
         self.subscriptions[address][0][txhash] = [1, len(self.peers)/2]
 def push_tx(self, tx_signed, raw=False):
     # push transactions requires a post to blockr
     path = '/tx/push'
     url = self._url + path
     payload = {'hex': tx_signed}
     response = requests.post(url, data=payload)
     if raw:
         return response
     return bitcoin.txhash(tx_signed)
Example #18
0
def direct_send(wallet, amount, mixdepth, destaddr, answeryes=False):
    """Send coins directly from one mixdepth to one destination address;
    does not need IRC. Sweep as for normal sendpayment (set amount=0).
    """
    #Sanity checks; note destaddr format is carefully checked in startup
    assert isinstance(mixdepth, int)
    assert mixdepth >= 0
    assert isinstance(amount, int)
    assert amount >= 0 and amount < 10000000000
    assert isinstance(wallet, Wallet)

    import bitcoin as btc
    from pprint import pformat
    if amount == 0:
        utxos = wallet.get_utxos_by_mixdepth()[mixdepth]
        if utxos == {}:
            log.error("There are no utxos in mixdepth: " + str(mixdepth) +
                      ", quitting.")
            return
        total_inputs_val = sum([va['value'] for u, va in utxos.iteritems()])
        fee_est = estimate_tx_fee(len(utxos), 1)
        outs = [{"address": destaddr, "value": total_inputs_val - fee_est}]
    else:
        initial_fee_est = estimate_tx_fee(8, 2)  #8 inputs to be conservative
        utxos = wallet.select_utxos(mixdepth, amount + initial_fee_est)
        if len(utxos) < 8:
            fee_est = estimate_tx_fee(len(utxos), 2)
        else:
            fee_est = initial_fee_est
        total_inputs_val = sum([va['value'] for u, va in utxos.iteritems()])
        changeval = total_inputs_val - fee_est - amount
        outs = [{"value": amount, "address": destaddr}]
        change_addr = wallet.get_internal_addr(mixdepth)
        outs.append({"value": changeval, "address": change_addr})

    #Now ready to construct transaction
    log.info("Using a fee of : " + str(fee_est) + " satoshis.")
    if amount != 0:
        log.info("Using a change value of: " + str(changeval) + " satoshis.")
    tx = btc.mktx(utxos.keys(), outs)
    stx = btc.deserialize(tx)
    for index, ins in enumerate(stx['ins']):
        utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index'])
        addr = utxos[utxo]['address']
        tx = btc.sign(tx, index, wallet.get_key_from_addr(addr))
    txsigned = btc.deserialize(tx)
    log.info("Got signed transaction:\n")
    log.info(tx + "\n")
    log.info(pformat(txsigned))
    if not answeryes:
        if raw_input(
                'Would you like to push to the network? (y/n):')[0] != 'y':
            log.info("You chose not to broadcast the transaction, quitting.")
            return
    jm_single().bc_interface.pushtx(tx)
    txid = btc.txhash(tx)
    log.info("Transaction sent: " + txid + ", shutting down")
    def push(self, tx):
        """
        Args:
            tx: hex of signed transaction
        Returns:
            pushed transaction

        """
        self._service.push_tx(tx)
        return bitcoin.txhash(tx)
Example #20
0
	def push(self, txd):
		tx = btc.serialize(txd)
		debug('\n' + tx)
		debug('txid = ' + btc.txhash(tx))
		#TODO send to a random maker or push myself
		#TODO need to check whether the other party sent it
		#self.msgchan.push_tx(self.active_orders.keys()[0], txhex)	
		self.txid = common.bc_interface.pushtx(tx)
		if self.txid == None:
			debug('unable to pushtx')
Example #21
0
 def push(self, txd):
     tx = btc.serialize(txd)
     debug('\n' + tx)
     debug('txid = ' + btc.txhash(tx))
     #TODO send to a random maker or push myself
     #TODO need to check whether the other party sent it
     #self.msgchan.push_tx(self.active_orders.keys()[0], txhex)
     self.txid = common.bc_interface.pushtx(tx)
     if self.txid == None:
         debug('unable to pushtx')
Example #22
0
    def push(self, tx):
        """
        Args:
            tx: hex of signed transaction
        Returns:
            pushed transaction

        """
        self._service.push_tx(tx)
        return bitcoin.txhash(tx)
Example #23
0
            def on_validate(success):
                def on_fetch(ec, result):
                    if ec:
                        # if it's not in the blockchain, let's try broadcasting it.
                        self.log.info("Broadcasting payout tx %s to network" %
                                      bitcoin.txhash(tx))
                        self.blockchain.broadcast(tx, cb=on_broadcast_complete)
                    else:
                        d.callback(order_id)

                if success:
                    # broadcast anyway but don't wait for callback
                    self.log.info("Broadcasting payout tx %s to network" %
                                  bitcoin.txhash(tx))
                    self.blockchain.broadcast(tx)
                    d.callback(order_id)
                else:
                    # check to see if the tx is already in the blockchain
                    self.blockchain.fetch_transaction(
                        unhexlify(bitcoin.txhash(tx)), on_fetch)
Example #24
0
    def on_tx_received(self, address_version, address_hash, height, block_hash, tx):
        """
        Fire when the libbitcoin server tells us we received a payment to this funding address.
        While unlikely, a user may send multiple transactions to the funding address to reach the
        funding level. We need to keep a running balance and increment it when a new transaction
        is received. If the contract is fully funded, we push a notification to the websockets.
        """

        # decode the transaction
        transaction = deserialize(tx.encode("hex"))

        # get the amount (in satoshi) the user is expected to pay
        amount_to_pay = int(float(self.contract["buyer_order"]["order"]["payment"]["amount"]) * 100000000)
        if tx not in self.received_txs:  # make sure we aren't parsing the same tx twice.
            output_script = 'a914' + digest(unhexlify(
                self.contract["buyer_order"]["order"]["payment"]["redeem_script"])).encode("hex") + '87'
            for output in transaction["outs"]:
                if output["script"] == output_script:
                    self.amount_funded += output["value"]
                    if tx not in self.received_txs:
                        self.received_txs.append(tx)
                    self.outpoints.append({"output": bitcoin.txhash(tx.encode("hex")) + ":" + str(output["index"]),
                                           "value": output["value"]})
            if self.amount_funded >= amount_to_pay:  # if fully funded
                self.timeout.cancel()
                self.blockchain.unsubscribe_address(
                    self.contract["buyer_order"]["order"]["payment"]["address"], self.on_tx_received)
                order_id = digest(json.dumps(self.contract, indent=4)).encode("hex")
                if self.is_purchase:
                    message_json = {
                        "payment_received": {
                            "address": self.contract["buyer_order"]["order"]["payment"]["address"],
                            "order_id": order_id
                            }
                    }

                    # update the db
                    self.db.Purchases().update_status(order_id, 1)
                    self.db.Purchases().update_outpoint(order_id, pickle.dumps(self.outpoints))
                    self.log.info("Payment for order id %s successfully broadcast to network." % order_id)
                else:
                    message_json = {
                        "new_order": {
                            "order_id": order_id,
                            "title": self.contract["vendor_offer"]["listing"]["item"]["title"]
                            }
                    }
                    self.db.Sales().update_status(order_id, 1)
                    self.db.Sales().update_outpoint(order_id, pickle.dumps(self.outpoints))
                    self.log.info("Received new order %s" % order_id)

                # push the message over websockets
                self.ws.push(json.dumps(message_json, indent=4))
def tx_verify( tx, tx_hash ):
    """
    Confirm that a bitcoin transaction has the given hash.
    """
    tx_serialized = tx_serialize( tx )
    tx_candidate_hash = bitcoin.txhash( tx_serialized )
    # tx_reversed_bin_hash = pybitcoin.bin_double_sha256( binascii.unhexlify(tx_serialized) )
    # tx_candidate_hash = binascii.hexlify(tx_reversed_bin_hash[::-1])

    if tx_hash != tx_candidate_hash:
        print tx_serialized

    return tx_hash == tx_candidate_hash
Example #26
0
 def pushPayment(self):
     #compliantScript = bitcoin.mk_multisig_script([bitcoin.privtopub(self.privS), self.pubKeyClient], 2,2)  # inversion!!!!
     compliantScript = bitcoin.mk_multisig_script(
         [self.pubKeyClient,
          bitcoin.privtopub(self.privS)], 2, 2)
     sigServer = bitcoin.multisign(self.lastpayment, 0, compliantScript,
                                   self.privS)
     signedPtx = bitcoin.apply_multisignatures(self.lastpayment, 0,
                                               compliantScript,
                                               [self.lastsig, sigServer])
     print 'Broadcast the very last payment. Just got richer. Tx hash:', bitcoin.txhash(
         signedPtx)
     bitcoin.pushtx(signedPtx)
Example #27
0
 def on_peer_announce(tx):
     txhash = bitcoin.txhash(bitcoin.serialize(tx["tx"]))
     if txhash in self.subscriptions[address][0] and self.subscriptions[
             address][0][txhash][0] != "complete":
         self.subscriptions[address][0][txhash][0] += 1
         if self.subscriptions[address][0][txhash][
                 0] >= self.subscriptions[address][0][txhash][1]:
             self.subscriptions[address][0][txhash][0] = "complete"
             self.subscriptions[address][1](tx["tx"])
     elif txhash not in self.subscriptions[address][0]:
         self.subscriptions[address][0][txhash] = [
             1, len(self.peers) / 2
         ]
Example #28
0
 def push(self, txd):
     tx = btc.serialize(txd)
     log.debug('\n' + tx)
     log.debug('txid = ' + btc.txhash(tx))
     # TODO send to a random maker or push myself
     # TODO need to check whether the other party sent it
     # self.msgchan.push_tx(self.active_orders.keys()[0], txhex)
     pushed = jm_single().bc_interface.pushtx(tx)
     if pushed[0]:
         self.txid = pushed[1]
     else:
         log.debug('unable to pushtx, reason: ' + str(pushed[1]))
     return pushed[0]
Example #29
0
    def broadcast_tx(self, tx):
        """
        Send the tx to half our peers, wait for half of the remainder to announce the tx before
        calling back True.
        """
        def on_peer_anncounce(txid):
            self.pending_txs[txid][0] += 1
            if self.pending_txs[txid][0] >= self.pending_txs[txid][1] / 2:
                if self.pending_txs[txid][3].active():
                    self.pending_txs[txid][3].cancel()
                    self.pending_txs[txid][2].callback(True)

        d = defer.Deferred()
        self.inventory[bitcoin.txhash(tx)] = tx
        inv_packet = inv("TX", bitcoin.txhash(tx))
        self.bloom_filter.insert(bitcoin.bin_txhash(tx))
        self.pending_txs[bitcoin.txhash(tx)] = [0, len(self.peers)/2, d, reactor.callLater(10, d.callback, False)]
        for peer in self.peers[len(self.peers)/2:]:
            peer.protocol.update_filter()
            peer.protocol.add_inv_callback(bitcoin.txhash(tx), on_peer_anncounce)
        for peer in self.peers[:len(self.peers)/2]:
            peer.protocol.send_message(message(inv_packet, self.params))
        return d
Example #30
0
	def self_sign_and_push(self):
		#now sign it ourselves
		tx = btc.serialize(self.latest_tx)
		for index, ins in enumerate(self.latest_tx['ins']):
			utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index'])
			if utxo not in self.input_utxos.keys():
				continue
			addr = self.input_utxos[utxo]['address']
			tx = btc.sign(tx, index, self.wallet.get_key_from_addr(addr))
		txhex = btc.serialize(self.latest_tx)
		debug('\n' + txhex)
		debug('txid = ' + btc.txhash(tx))
		#TODO send to a random maker or push myself
		#TODO need to check whether the other party sent it
		#self.msgchan.push_tx(self.active_orders.keys()[0], txhex)	
		self.txid = common.bc_interface.pushtx(tx)
		if self.txid == None:
			debug('unable to pushtx')
Example #31
0
def get_txs_and_heights(outs):
    txs = {}
    heights = {}
    for i in range(0, len(outs), 20):
        txhashes = []
        fetched_heights = []
        for j in range(i, min(i + 20, len(outs))):
            if outs[j]['output'][65:] == '0':
                txhashes.append(outs[j]['output'][:64])
                fetched_heights.append(outs[j]['block_height'])
            else:
                sys.stderr.write("Non-purchase tx found (genesis output index not zero): %s\n" %
                                 outs[j]['output'][:64])
        fetched_txs = fetchtx(txhashes)
        assert len(fetched_txs) == len(txhashes) == len(fetched_heights)
        for h, tx, ht in zip(txhashes, fetched_txs, fetched_heights):
            assert b.txhash(str(tx)) == h
            txs[h] = tx
            heights[h] = ht
        sys.stderr.write('Processed transactions: %d\n' % len(txs))
    return {"txs": txs, "heights": heights}
Example #32
0
def get_txs_and_heights(outs):
    txs = {}
    heights = {}
    for i in range(0, len(outs), 20):
        txhashes = []
        fetched_heights = []
        for j in range(i, min(i + 20, len(outs))):
            if outs[j]['output'][65:] == '0':
                txhashes.append(outs[j]['output'][:64])
                fetched_heights.append(outs[j]['block_height'])
            else:
                sys.stderr.write("Non-purchase tx found (genesis output index not zero): %s\n" %
                                 outs[j]['output'][:64])
        fetched_txs = fetchtx(txhashes)
        assert len(fetched_txs) == len(txhashes) == len(fetched_heights)
        for h, tx, ht in zip(txhashes, fetched_txs, fetched_heights):
            assert b.txhash(str(tx)) == h
            txs[h] = tx
            heights[h] = ht
        sys.stderr.write('Processed transactions: %d\n' % len(txs))
    return {"txs": txs, "heights": heights}
Example #33
0
    def push(self):
        tx = btc.serialize(self.latest_tx)
        log.debug('\n' + tx)
        self.txid = btc.txhash(tx)
        log.info('txid = ' + self.txid)

        tx_broadcast = jm_single().config.get('POLICY', 'tx_broadcast')
        if tx_broadcast == 'self':
            pushed = jm_single().bc_interface.pushtx(tx)
        elif tx_broadcast in ['random-peer', 'not-self']:
            n = len(self.active_orders)
            if tx_broadcast == 'random-peer':
                i = random.randrange(n + 1)
            else:
                i = random.randrange(n)
            if i == n:
                pushed = jm_single().bc_interface.pushtx(tx)
            else:
                self.msgchan.push_tx(self.active_orders.keys()[i], tx)
                pushed = True
        elif tx_broadcast == 'random-maker':
            crow = self.db.execute(
                'SELECT DISTINCT counterparty FROM orderbook ORDER BY ' +
                'RANDOM() LIMIT 1;'
            ).fetchone()
            counterparty = crow['counterparty']
            log.info('pushing tx to ' + counterparty)
            self.msgchan.push_tx(counterparty, tx)
            pushed = True
        elif tx_broadcast == 'tor':
            socks5_host = jm_single().config.get("MESSAGING",
                "socks5_host").split(",")[0]
            socks5_port = int(jm_single().config.get("MESSAGING",
                "socks5_port").split(",")[0])
            pushed = tor_broadcast_tx(tx, (socks5_host, socks5_port),
                testnet=(get_network() == "testnet"))

        if not pushed:
            log.error('unable to pushtx')
        return pushed
Example #34
0
    def push(self):
        tx = btc.serialize(self.latest_tx)
        log.debug('\n' + tx)
        self.txid = btc.txhash(tx)
        log.info('txid = ' + self.txid)

        tx_broadcast = jm_single().config.get('POLICY', 'tx_broadcast')
        if tx_broadcast == 'self':
            pushed = jm_single().bc_interface.pushtx(tx)
        elif tx_broadcast in ['random-peer', 'not-self']:
            n = len(self.active_orders)
            if tx_broadcast == 'random-peer':
                i = random.randrange(n + 1)
            else:
                i = random.randrange(n)
            if i == n:
                pushed = jm_single().bc_interface.pushtx(tx)
            else:
                self.msgchan.push_tx(self.active_orders.keys()[i], tx)
                pushed = True
        elif tx_broadcast == 'random-maker':
            crow = self.db.execute(
                'SELECT DISTINCT counterparty FROM orderbook ORDER BY ' +
                'RANDOM() LIMIT 1;').fetchone()
            counterparty = crow['counterparty']
            log.info('pushing tx to ' + counterparty)
            self.msgchan.push_tx(counterparty, tx)
            pushed = True
        elif tx_broadcast == 'tor':
            socks5_host = jm_single().config.get("MESSAGING",
                                                 "socks5_host").split(",")[0]
            socks5_port = int(jm_single().config.get(
                "MESSAGING", "socks5_port").split(",")[0])
            pushed = tor_broadcast_tx(tx, (socks5_host, socks5_port),
                                      testnet=(get_network() == "testnet"))

        if not pushed:
            log.error('unable to pushtx')
        return pushed
Example #35
0
def test_donation_address(setup_donations, amount):
    wallets = make_wallets(1, wallet_structures=[[1,1,1,0,0]],
                               mean_amt=0.5)
    wallet = wallets[0]['wallet']
    jm_single().bc_interface.sync_wallet(wallet)
    #make a rdp from a simple privkey
    rdp_priv = "\x01"*32
    reusable_donation_pubkey = binascii.hexlify(secp256k1.PrivateKey(
        privkey=rdp_priv, raw=True, ctx=btc.ctx).pubkey.serialize())    
    dest_addr, sign_k = donation_address(reusable_donation_pubkey)
    print dest_addr
    jm_single().bc_interface.rpc('importaddress',
                                [dest_addr, '', False])    
    ins_full = wallet.unspent
    total = sum(x['value'] for x in ins_full.values())
    ins = ins_full.keys()
    output_addr = wallet.get_new_addr(1, 1)
    fee_est = 10000
    outs = [{'value': amount,
             'address': dest_addr}, {'value': total - amount - fee_est,
                                       'address': output_addr}]

    tx = btc.mktx(ins, outs)
    de_tx = btc.deserialize(tx)
    for index, ins in enumerate(de_tx['ins']):
        utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index'])
        addr = ins_full[utxo]['address']
        priv = wallet.get_key_from_addr(addr)
        priv = binascii.unhexlify(priv)
        usenonce = binascii.unhexlify(sign_k) if index == 0 else None
        if index == 0:
            log.debug("Applying rdp to input: " + str(ins))
        tx = btc.sign(tx, index, priv, usenonce=usenonce)
    #pushtx returns False on any error
    push_succeed = jm_single().bc_interface.pushtx(tx)
    if push_succeed:
        log.debug(btc.txhash(tx))
    else:
        assert False
    #Role of receiver: regenerate the destination private key,
    #and address, from the nonce of the first input; check it has
    #received the coins.
    detx = btc.deserialize(tx)
    first_utxo_script = detx['ins'][0]['script']
    sig, pub = btc.deserialize_script(first_utxo_script)
    log.debug(sig)
    sig = binascii.unhexlify(sig)
    kGlen = ord(sig[3])
    kG = sig[4:4+kGlen]
    log.debug(binascii.hexlify(kG))
    if kG[0] == "\x00":
        kG = kG[1:]
    #H(rdp private key * K) + rdp should be ==> dest addr
    #Open issue: re-introduce recovery without ECC shenanigans
    #Just cheat by trying both signs for pubkey
    coerced_kG_1 = "02" + binascii.hexlify(kG)
    coerced_kG_2 = "03" + binascii.hexlify(kG)
    for coerc in [coerced_kG_1, coerced_kG_2]:
        c = btc.sha256(btc.multiply(binascii.hexlify(rdp_priv), coerc, True))
        pub_check = btc.add_pubkeys([reusable_donation_pubkey,
                                     btc.privtopub(c+'01', True)], True)
        addr_check = btc.pubtoaddr(pub_check, get_p2pk_vbyte())
        log.debug("Found checked address: " + addr_check)
        if addr_check == dest_addr:
            time.sleep(3)
            received = jm_single().bc_interface.get_received_by_addr(
                    [dest_addr], None)['data'][0]['balance']
            assert received == amount
            return
    assert False
Example #36
0
    def accept_receipt(self, ws, blockchain, receipt_json=None):
        """
        Process the final receipt sent over by the buyer. If valid, broadcast the transaction
        to the bitcoin network.
        """
        self.ws = ws
        self.blockchain = blockchain
        try:
            if receipt_json:
                self.contract["buyer_receipt"] = json.loads(
                    receipt_json, object_pairs_hook=OrderedDict)
            contract_dict = json.loads(json.dumps(self.contract, indent=4),
                                       object_pairs_hook=OrderedDict)
            del contract_dict["buyer_receipt"]
            contract_hash = digest(json.dumps(contract_dict,
                                              indent=4)).encode("hex")
            ref_hash = self.contract["buyer_receipt"]["receipt"]["ref_hash"]
            if ref_hash != contract_hash:
                raise Exception("Order number doesn't match")

            # The buyer may have sent over this whole contract, make sure the data we added wasn't manipulated.
            verify_key = self.keychain.signing_key.verify_key
            verify_key.verify(
                json.dumps(
                    self.contract["vendor_order_confirmation"]["invoice"],
                    indent=4),
                unhexlify(
                    self.contract["vendor_order_confirmation"]["signature"]))

            order_id = self.contract["vendor_order_confirmation"]["invoice"][
                "ref_hash"]
            outpoints = pickle.loads(self.db.Sales().get_outpoint(order_id))
            payout_address = self.contract["vendor_order_confirmation"][
                "invoice"]["payout"]["address"]
            redeem_script = str(self.contract["buyer_order"]["order"]
                                ["payment"]["redeem_script"])
            for output in outpoints:
                del output["value"]
            value = self.contract["vendor_order_confirmation"]["invoice"][
                "payout"]["value"]
            outs = [{'value': value, 'address': payout_address}]
            tx = bitcoin.mktx(outpoints, outs)

            chaincode = self.contract["buyer_order"]["order"]["payment"][
                "chaincode"]
            masterkey_b = self.contract["buyer_order"]["order"]["id"][
                "pubkeys"]["bitcoin"]
            buyer_key = derive_childkey(masterkey_b, chaincode)

            vendor_sigs = self.contract["vendor_order_confirmation"][
                "invoice"]["payout"]["signature(s)"]
            buyer_sigs = self.contract["buyer_receipt"]["receipt"]["payout"][
                "signature(s)"]
            for index in range(0, len(outpoints)):
                for s in vendor_sigs:
                    if s["input_index"] == index:
                        sig1 = str(s["signature"])
                for s in buyer_sigs:
                    if s["input_index"] == index:
                        sig2 = str(s["signature"])

                if bitcoin.verify_tx_input(tx, index, redeem_script, sig2,
                                           buyer_key):
                    tx = bitcoin.apply_multisignatures(tx, index,
                                                       str(redeem_script),
                                                       sig1, sig2)
                else:
                    raise Exception("Buyer sent invalid signature")

            d = defer.Deferred()

            def on_broadcast_complete(success):
                if success:
                    d.callback(order_id)
                else:
                    d.callback(False)

            def on_validate(success):
                def on_fetch(ec, result):
                    if ec:
                        # if it's not in the blockchain, let's try broadcasting it.
                        self.log.info("Broadcasting payout tx %s to network" %
                                      bitcoin.txhash(tx))
                        self.blockchain.broadcast(tx, cb=on_broadcast_complete)
                    else:
                        d.callback(order_id)

                if success:
                    # broadcast anyway but don't wait for callback
                    self.log.info("Broadcasting payout tx %s to network" %
                                  bitcoin.txhash(tx))
                    self.blockchain.broadcast(tx)
                    d.callback(order_id)
                else:
                    # check to see if the tx is already in the blockchain
                    self.blockchain.fetch_transaction(
                        unhexlify(bitcoin.txhash(tx)), on_fetch)

            if "txid" in self.contract["buyer_receipt"]["receipt"]["payout"] \
                    and bitcoin.txhash(tx) == self.contract["buyer_receipt"]["receipt"]["payout"]["txid"]:
                # check mempool and blockchain for tx
                self.blockchain.validate(tx, cb=on_validate)
            else:
                # try broadcasting
                self.log.info("Broadcasting payout tx %s to network" %
                              bitcoin.txhash(tx))
                self.blockchain.broadcast(tx, cb=on_broadcast_complete)

            # TODO: update db and file system if successful
            # TODO: broadcast over websocket
            return d

        except Exception:
            return defer.succeed(False)
Example #37
0
    def on_tx_received(self, address_version, address_hash, height, block_hash,
                       tx):
        """
        Fire when the libbitcoin server tells us we received a payment to this funding address.
        While unlikely, a user may send multiple transactions to the funding address to reach the
        funding level. We need to keep a running balance and increment it when a new transaction
        is received. If the contract is fully funded, we push a notification to the websockets.
        """

        # decode the transaction
        transaction = deserialize(tx.encode("hex"))

        # get the amount (in satoshi) the user is expected to pay
        amount_to_pay = int(
            float(self.contract["buyer_order"]["order"]["payment"]["amount"]) *
            100000000)
        if tx not in self.received_txs:  # make sure we aren't parsing the same tx twice.
            output_script = 'a914' + digest(
                unhexlify(self.contract["buyer_order"]["order"]["payment"]
                          ["redeem_script"])).encode("hex") + '87'
            for output in transaction["outs"]:
                if output["script"] == output_script:
                    self.amount_funded += output["value"]
                    if tx not in self.received_txs:
                        self.received_txs.append(tx)
                    self.outpoints.append({
                        "output":
                        bitcoin.txhash(tx.encode("hex")) + ":" +
                        str(output["index"]),
                        "value":
                        output["value"]
                    })
            if self.amount_funded >= amount_to_pay:  # if fully funded
                self.timeout.cancel()
                self.blockchain.unsubscribe_address(
                    self.contract["buyer_order"]["order"]["payment"]
                    ["address"], self.on_tx_received)
                order_id = digest(json.dumps(self.contract,
                                             indent=4)).encode("hex")
                if self.is_purchase:
                    message_json = {
                        "payment_received": {
                            "address":
                            self.contract["buyer_order"]["order"]["payment"]
                            ["address"],
                            "order_id":
                            order_id
                        }
                    }

                    # update the db
                    self.db.Purchases().update_status(order_id, 1)
                    self.db.Purchases().update_outpoint(
                        order_id, pickle.dumps(self.outpoints))
                    self.log.info(
                        "Payment for order id %s successfully broadcast to network."
                        % order_id)
                else:
                    message_json = {
                        "new_order": {
                            "order_id":
                            order_id,
                            "title":
                            self.contract["vendor_offer"]["listing"]["item"]
                            ["title"]
                        }
                    }
                    self.db.Sales().update_status(order_id, 1)
                    self.db.Sales().update_outpoint(
                        order_id, pickle.dumps(self.outpoints))
                    self.log.info("Received new order %s" % order_id)

                # push the message over websockets
                self.ws.push(json.dumps(message_json, indent=4))
Example #38
0
 def __init__(self, hexstr):
     self.hexstr = hexstr
     self.decoded = bitcoin.deserialize(hexstr)
     self.hsh = bitcoin.txhash(hexstr)
     self.handle = "BCH_" + self.hsh
Example #39
0
    def accept_receipt(self, ws, blockchain, receipt_json=None):
        """
        Process the final receipt sent over by the buyer. If valid, broadcast the transaction
        to the bitcoin network.
        """
        self.ws = ws
        self.blockchain = blockchain
        try:
            if receipt_json:
                self.contract["buyer_receipt"] = json.loads(receipt_json,
                                                            object_pairs_hook=OrderedDict)
            contract_dict = json.loads(json.dumps(self.contract, indent=4), object_pairs_hook=OrderedDict)
            del contract_dict["buyer_receipt"]
            contract_hash = digest(json.dumps(contract_dict, indent=4)).encode("hex")
            ref_hash = self.contract["buyer_receipt"]["receipt"]["ref_hash"]
            if ref_hash != contract_hash:
                raise Exception("Order number doesn't match")

            # The buyer may have sent over this whole contract, make sure the data we added wasn't manipulated.
            verify_key = self.keychain.signing_key.verify_key
            verify_key.verify(json.dumps(self.contract["vendor_order_confirmation"]["invoice"], indent=4),
                              unhexlify(self.contract["vendor_order_confirmation"]["signature"]))

            order_id = self.contract["vendor_order_confirmation"]["invoice"]["ref_hash"]
            outpoints = pickle.loads(self.db.Sales().get_outpoint(order_id))
            payout_address = self.contract["vendor_order_confirmation"]["invoice"]["payout"]["address"]
            redeem_script = str(self.contract["buyer_order"]["order"]["payment"]["redeem_script"])
            for output in outpoints:
                del output["value"]
            value = self.contract["vendor_order_confirmation"]["invoice"]["payout"]["value"]
            outs = [{'value': value, 'address': payout_address}]
            tx = bitcoin.mktx(outpoints, outs)

            chaincode = self.contract["buyer_order"]["order"]["payment"]["chaincode"]
            masterkey_b = self.contract["buyer_order"]["order"]["id"]["pubkeys"]["bitcoin"]
            buyer_key = derive_childkey(masterkey_b, chaincode)

            vendor_sigs = self.contract["vendor_order_confirmation"]["invoice"]["payout"]["signature(s)"]
            buyer_sigs = self.contract["buyer_receipt"]["receipt"]["payout"]["signature(s)"]
            for index in range(0, len(outpoints)):
                for s in vendor_sigs:
                    if s["input_index"] == index:
                        sig1 = str(s["signature"])
                for s in buyer_sigs:
                    if s["input_index"] == index:
                        sig2 = str(s["signature"])

                if bitcoin.verify_tx_input(tx, index, redeem_script, sig2, buyer_key):
                    tx = bitcoin.apply_multisignatures(tx, index, str(redeem_script), sig1, sig2)
                else:
                    raise Exception("Buyer sent invalid signature")

            d = defer.Deferred()

            def on_broadcast_complete(success):
                if success:
                    d.callback(order_id)
                else:
                    d.callback(False)

            def on_validate(success):
                def on_fetch(ec, result):
                    if ec:
                        # if it's not in the blockchain, let's try broadcasting it.
                        self.log.info("Broadcasting payout tx %s to network" % bitcoin.txhash(tx))
                        self.blockchain.broadcast(tx, cb=on_broadcast_complete)
                    else:
                        d.callback(order_id)

                if success:
                    # broadcast anyway but don't wait for callback
                    self.log.info("Broadcasting payout tx %s to network" % bitcoin.txhash(tx))
                    self.blockchain.broadcast(tx)
                    d.callback(order_id)
                else:
                    # check to see if the tx is already in the blockchain
                    self.blockchain.fetch_transaction(unhexlify(bitcoin.txhash(tx)), on_fetch)

            if "txid" in self.contract["buyer_receipt"]["receipt"]["payout"] \
                    and bitcoin.txhash(tx) == self.contract["buyer_receipt"]["receipt"]["payout"]["txid"]:
                # check mempool and blockchain for tx
                self.blockchain.validate(tx, cb=on_validate)
            else:
                # try broadcasting
                self.log.info("Broadcasting payout tx %s to network" % bitcoin.txhash(tx))
                self.blockchain.broadcast(tx, cb=on_broadcast_complete)

            # TODO: update db and file system if successful
            # TODO: broadcast over websocket
            return d

        except Exception:
            return defer.succeed(False)
Example #40
0
def txid(tx): return b.txhash(tx)
def serialize(x): 
Example #41
0
def txid(tx):
    return b.txhash(tx)
Example #42
0
 def add_receipt(self,
                 received,
                 libbitcoin_client,
                 feedback=None,
                 quality=None,
                 description=None,
                 delivery_time=None,
                 customer_service=None,
                 review="",
                 dispute=False,
                 claim=None,
                 payout=True):
     """
     Add the final piece of the contract that appends the review and payout transaction.
     """
     self.blockchain = libbitcoin_client
     receipt_json = {
         "buyer_receipt": {
             "receipt": {
                 "ref_hash":
                 digest(json.dumps(self.contract, indent=4)).encode("hex"),
                 "listing": {
                     "received":
                     received,
                     "listing_hash":
                     self.contract["buyer_order"]["order"]["ref_hash"]
                 },
                 "dispute": {
                     "dispute": dispute
                 }
             }
         }
     }
     if None not in (feedback, quality, description, delivery_time,
                     customer_service):
         receipt_json["buyer_receipt"]["receipt"]["rating"] = {}
         receipt_json["buyer_receipt"]["receipt"]["rating"][
             "feedback"] = feedback
         receipt_json["buyer_receipt"]["receipt"]["rating"][
             "quality"] = quality
         receipt_json["buyer_receipt"]["receipt"]["rating"][
             "description"] = description
         receipt_json["buyer_receipt"]["receipt"]["rating"][
             "delivery_time"] = delivery_time
         receipt_json["buyer_receipt"]["receipt"]["rating"][
             "customer_service"] = customer_service
         receipt_json["buyer_receipt"]["receipt"]["rating"][
             "review"] = review
     if payout:
         order_id = self.contract["vendor_order_confirmation"]["invoice"][
             "ref_hash"]
         outpoints = pickle.loads(
             self.db.Purchases().get_outpoint(order_id))
         payout_address = self.contract["vendor_order_confirmation"][
             "invoice"]["payout"]["address"]
         redeem_script = str(self.contract["buyer_order"]["order"]
                             ["payment"]["redeem_script"])
         for output in outpoints:
             del output["value"]
         value = self.contract["vendor_order_confirmation"]["invoice"][
             "payout"]["value"]
         outs = [{'value': value, 'address': payout_address}]
         tx = bitcoin.mktx(outpoints, outs)
         signatures = []
         chaincode = self.contract["buyer_order"]["order"]["payment"][
             "chaincode"]
         masterkey_b = bitcoin.bip32_extract_key(
             self.keychain.bitcoin_master_privkey)
         buyer_priv = derive_childkey(masterkey_b, chaincode,
                                      bitcoin.MAINNET_PRIVATE)
         masterkey_v = self.contract["vendor_offer"]["listing"]["id"][
             "pubkeys"]["bitcoin"]
         vendor_key = derive_childkey(masterkey_v, chaincode)
         valid_inputs = 0
         for index in range(0, len(outpoints)):
             sig = bitcoin.multisign(tx, index, redeem_script, buyer_priv)
             signatures.append({"input_index": index, "signature": sig})
             for s in self.contract["vendor_order_confirmation"]["invoice"][
                     "payout"]["signature(s)"]:
                 if s["input_index"] == index:
                     if bitcoin.verify_tx_input(tx, index, redeem_script,
                                                s["signature"], vendor_key):
                         tx = bitcoin.apply_multisignatures(
                             tx, index, str(redeem_script), sig,
                             str(s["signature"]))
                         valid_inputs += 1
         receipt_json["buyer_receipt"]["receipt"]["payout"] = {}
         if valid_inputs == len(outpoints):
             self.log.info("Broadcasting payout tx %s to network" %
                           bitcoin.txhash(tx))
             self.blockchain.broadcast(tx)
             receipt_json["buyer_receipt"]["receipt"]["payout"][
                 "txid"] = bitcoin.txhash(tx)
         receipt_json["buyer_receipt"]["receipt"]["payout"][
             "signature(s)"] = signatures
         receipt_json["buyer_receipt"]["receipt"]["payout"]["value"] = value
     if claim:
         receipt_json["buyer_receipt"]["receipt"]["dispute"][
             "claim"] = claim
     receipt = json.dumps(receipt_json["buyer_receipt"]["receipt"],
                          indent=4)
     receipt_json["buyer_receipt"]["signature"] = \
         self.keychain.signing_key.sign(receipt, encoder=nacl.encoding.HexEncoder)[:128]
     self.contract["buyer_receipt"] = receipt_json["buyer_receipt"]
Example #43
0
def test_donation_address(setup_donations, amount):
    wallets = make_wallets(1,
                           wallet_structures=[[1, 1, 1, 0, 0]],
                           mean_amt=0.5)
    wallet = wallets[0]['wallet']
    jm_single().bc_interface.sync_wallet(wallet)
    #make a rdp from a simple privkey
    rdp_priv = "\x01" * 32
    reusable_donation_pubkey = binascii.hexlify(
        secp256k1.PrivateKey(privkey=rdp_priv, raw=True,
                             ctx=btc.ctx).pubkey.serialize())
    dest_addr, sign_k = donation_address(reusable_donation_pubkey)
    print dest_addr
    jm_single().bc_interface.rpc('importaddress', [dest_addr, '', False])
    ins_full = wallet.unspent
    total = sum(x['value'] for x in ins_full.values())
    ins = ins_full.keys()
    output_addr = wallet.get_new_addr(1, 1)
    fee_est = 10000
    outs = [{
        'value': amount,
        'address': dest_addr
    }, {
        'value': total - amount - fee_est,
        'address': output_addr
    }]

    tx = btc.mktx(ins, outs)
    de_tx = btc.deserialize(tx)
    for index, ins in enumerate(de_tx['ins']):
        utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index'])
        addr = ins_full[utxo]['address']
        priv = wallet.get_key_from_addr(addr)
        priv = binascii.unhexlify(priv)
        usenonce = binascii.unhexlify(sign_k) if index == 0 else None
        if index == 0:
            log.debug("Applying rdp to input: " + str(ins))
        tx = btc.sign(tx, index, priv, usenonce=usenonce)
    #pushtx returns False on any error
    push_succeed = jm_single().bc_interface.pushtx(tx)
    if push_succeed:
        log.debug(btc.txhash(tx))
    else:
        assert False
    #Role of receiver: regenerate the destination private key,
    #and address, from the nonce of the first input; check it has
    #received the coins.
    detx = btc.deserialize(tx)
    first_utxo_script = detx['ins'][0]['script']
    sig, pub = btc.deserialize_script(first_utxo_script)
    log.debug(sig)
    sig = binascii.unhexlify(sig)
    kGlen = ord(sig[3])
    kG = sig[4:4 + kGlen]
    log.debug(binascii.hexlify(kG))
    if kG[0] == "\x00":
        kG = kG[1:]
    #H(rdp private key * K) + rdp should be ==> dest addr
    #Open issue: re-introduce recovery without ECC shenanigans
    #Just cheat by trying both signs for pubkey
    coerced_kG_1 = "02" + binascii.hexlify(kG)
    coerced_kG_2 = "03" + binascii.hexlify(kG)
    for coerc in [coerced_kG_1, coerced_kG_2]:
        c = btc.sha256(btc.multiply(binascii.hexlify(rdp_priv), coerc, True))
        pub_check = btc.add_pubkeys(
            [reusable_donation_pubkey,
             btc.privtopub(c + '01', True)], True)
        addr_check = btc.pubtoaddr(pub_check, get_p2pk_vbyte())
        log.debug("Found checked address: " + addr_check)
        if addr_check == dest_addr:
            time.sleep(3)
            received = jm_single().bc_interface.get_received_by_addr(
                [dest_addr], None)['data'][0]['balance']
            assert received == amount
            return
    assert False
Example #44
0
def tx_deserialize(tx_hex):
    """
    Given a serialized transaction, return its inputs, outputs, locktime, and version
    Each input will have:
    * txid: string 
    * vout: int 
    * [optional] sequence: int 
    * [optional] scriptSig: {"asm": ..., "hex": ...}
    
    Each output will have:
    * value: Decimal (in BTC)
    * script_hex: string 

    Return tx, formatted as {'locktime': ..., 'version': ..., 'vin': ..., 'vout': ...}
    """

    tx = bitcoin.deserialize(tx_hex)
    inputs = tx["ins"]
    outputs = tx["outs"]

    ret_inputs = []
    ret_outputs = []

    for inp in inputs:
        ret_inp = {
            "txid": inp["outpoint"]["hash"],
            "vout": int(inp["outpoint"]["index"]),
        }

        if "sequence" in inp:
            ret_inp["sequence"] = int(inp["sequence"])

        if "script" in inp:
            ret_inp["scriptSig"] = {
                "asm": tx_script_to_asm(inp['script']),
                "hex": inp["script"]
            }

        ret_inputs.append(ret_inp)

    for i in xrange(0, len(outputs)):
        out = outputs[i]

        assert len(
            out['script']
        ) > 0, "Invalid transaction scriptpubkey:\n%s" % simplejson.dumps(
            tx, indent=4, sort_keys=True)
        assert out['value'] < 1000 * (
            10**8), "High transaction value\n%s" % simplejson.dumps(
                tx, indent=4, sort_keys=True)

        ret_out = {
            "n": i,
            "value": Decimal(out["value"]) / 10**8,
            "scriptPubKey": {
                "hex": out["script"],
                "asm": tx_script_to_asm(out['script'])
            },

            # compat with pybitcoin
            "script_hex": out["script"]
        }

        ret_outputs.append(ret_out)

    ret = {
        "txid": bitcoin.txhash(tx_hex),
        "hex": tx_hex,
        "size": len(tx_hex) / 2,
        "locktime": tx['locktime'],
        "version": tx['version'],
        "vin": ret_inputs,
        "vout": ret_outputs
    }

    return ret
Example #45
0
    def add_signature(self, nick, sigb64):
        if nick not in self.nonrespondants:
            debug('add_signature => nick=' + nick + ' not in nonrespondants ' +
                  str(self.nonrespondants))
            return
        sig = base64.b64decode(sigb64).encode('hex')
        inserted_sig = False
        txhex = btc.serialize(self.latest_tx)

        #batch retrieval of utxo data
        utxo = {}
        ctr = 0
        for index, ins in enumerate(self.latest_tx['ins']):
            utxo_for_checking = ins['outpoint']['hash'] + ':' + str(
                ins['outpoint']['index'])
            if ins['script'] != '' or utxo_for_checking in self.input_utxos.keys(
            ):
                continue
            utxo[ctr] = [index, utxo_for_checking]
            ctr += 1
        utxo_data = common.bc_interface.query_utxo_set(
            [x[1] for x in utxo.values()])
        #insert signatures
        for i, u in utxo.iteritems():
            if utxo_data[i] == None:
                continue
            sig_good = btc.verify_tx_input(txhex, u[0], utxo_data[i]['script'],
                                           *btc.deserialize_script(sig))
            if sig_good:
                debug('found good sig at index=%d' % (u[0]))
                self.latest_tx['ins'][u[0]]['script'] = sig
                inserted_sig = True
                #check if maker has sent everything possible
                self.utxos[nick].remove(u[1])
                if len(self.utxos[nick]) == 0:
                    debug('nick = ' + nick +
                          ' sent all sigs, removing from nonrespondant list')
                    self.nonrespondants.remove(nick)
                break
        if not inserted_sig:
            debug('signature did not match anything in the tx')
            #TODO what if the signature doesnt match anything
            # nothing really to do except drop it, carry on and wonder why the
            # other guy sent a failed signature

        tx_signed = True
        for ins in self.latest_tx['ins']:
            if ins['script'] == '':
                tx_signed = False
        if not tx_signed:
            return
        self.end_timeout_thread = True
        self.all_responded = True
        with self.timeout_lock:
            self.timeout_lock.notify()
        debug('the entire tx is signed, ready to pushtx()')
        txhex = btc.serialize(self.latest_tx)
        debug('\n' + txhex)
        self.txid = btc.txhash(txhex)
        debug('pushing tx ' + self.txid)

        if self.finishcallback != None:
            self.finishcallback(self)
        #TODO send to a random maker or push myself
        #self.msgchan.push_tx(self.active_orders.keys()[0], txhex)
        ret = None
        ret = common.bc_interface.pushtx(txhex)
        if ret == None:
            debug('unable to pushtx')
Example #46
0
def txid(tx): return b.txhash(tx)
SIGHASH_ALL=1
def tx_deserialize( tx_hex ):
    """
    Given a serialized transaction, return its inputs, outputs, locktime, and version
    Each input will have:
    * txid: string 
    * vout: int 
    * [optional] sequence: int 
    * [optional] scriptSig: {"asm": ..., "hex": ...}
    
    Each output will have:
    * value: Decimal (in BTC)
    * script_hex: string 

    Return tx, formatted as {'locktime': ..., 'version': ..., 'vin': ..., 'vout': ...}
    """
    
    tx = bitcoin.deserialize( tx_hex )
    inputs = tx["ins"]
    outputs = tx["outs"]
    
    ret_inputs = []
    ret_outputs = []
   
    for inp in inputs:
        ret_inp = {
            "txid": inp["outpoint"]["hash"],
            "vout": int(inp["outpoint"]["index"]),
        }
        
        if "sequence" in inp:
            ret_inp["sequence"] = int(inp["sequence"])
            
        if "script" in inp:
            ret_inp["scriptSig"] = {
                "asm": tx_script_to_asm(inp['script']),
                "hex": inp["script"]
            }
            
        ret_inputs.append( ret_inp )
        
    for i in xrange(0, len(outputs)):
        out = outputs[i]
        
        assert len(out['script']) > 0, "Invalid transaction scriptpubkey:\n%s" % simplejson.dumps(tx, indent=4, sort_keys=True)
        assert out['value'] < 1000 * (10**8), "High transaction value\n%s" % simplejson.dumps(tx, indent=4, sort_keys=True)

        ret_out = {
            "n": i,
            "value": Decimal(out["value"]) / 10**8,
            "scriptPubKey": {
                "hex": out["script"],
                "asm": tx_script_to_asm(out['script'])
            },

            # compat with pybitcoin
            "script_hex": out["script"]
        }
        
        ret_outputs.append( ret_out )
        
    ret = {
        "txid": bitcoin.txhash(tx_hex),
        "hex": tx_hex,
        "size": len(tx_hex) / 2,
        "locktime": tx['locktime'],
        "version": tx['version'],
        "vin": ret_inputs,
        "vout": ret_outputs
    }

    return ret
Example #48
0
    def add_receipt(self,
                    received,
                    libbitcoin_client,
                    feedback=None,
                    quality=None,
                    description=None,
                    delivery_time=None,
                    customer_service=None,
                    review="",
                    dispute=False,
                    claim=None,
                    payout=True):

        """
        Add the final piece of the contract that appends the review and payout transaction.
        """
        self.blockchain = libbitcoin_client
        receipt_json = {
            "buyer_receipt": {
                "receipt": {
                    "ref_hash": digest(json.dumps(self.contract, indent=4)).encode("hex"),
                    "listing": {
                        "received": received,
                        "listing_hash": self.contract["buyer_order"]["order"]["ref_hash"]
                    },
                    "dispute": {
                        "dispute": dispute
                    }
                }
            }
        }
        if None not in (feedback, quality, description, delivery_time, customer_service):
            receipt_json["buyer_receipt"]["receipt"]["rating"] = {}
            receipt_json["buyer_receipt"]["receipt"]["rating"]["feedback"] = feedback
            receipt_json["buyer_receipt"]["receipt"]["rating"]["quality"] = quality
            receipt_json["buyer_receipt"]["receipt"]["rating"]["description"] = description
            receipt_json["buyer_receipt"]["receipt"]["rating"]["delivery_time"] = delivery_time
            receipt_json["buyer_receipt"]["receipt"]["rating"]["customer_service"] = customer_service
            receipt_json["buyer_receipt"]["receipt"]["rating"]["review"] = review
        if payout:
            order_id = self.contract["vendor_order_confirmation"]["invoice"]["ref_hash"]
            outpoints = pickle.loads(self.db.Purchases().get_outpoint(order_id))
            payout_address = self.contract["vendor_order_confirmation"]["invoice"]["payout"]["address"]
            redeem_script = str(self.contract["buyer_order"]["order"]["payment"]["redeem_script"])
            for output in outpoints:
                del output["value"]
            value = self.contract["vendor_order_confirmation"]["invoice"]["payout"]["value"]
            outs = [{'value': value, 'address': payout_address}]
            tx = bitcoin.mktx(outpoints, outs)
            signatures = []
            chaincode = self.contract["buyer_order"]["order"]["payment"]["chaincode"]
            masterkey_b = bitcoin.bip32_extract_key(self.keychain.bitcoin_master_privkey)
            buyer_priv = derive_childkey(masterkey_b, chaincode, bitcoin.MAINNET_PRIVATE)
            masterkey_v = self.contract["vendor_offer"]["listing"]["id"]["pubkeys"]["bitcoin"]
            vendor_key = derive_childkey(masterkey_v, chaincode)
            valid_inputs = 0
            for index in range(0, len(outpoints)):
                sig = bitcoin.multisign(tx, index, redeem_script, buyer_priv)
                signatures.append({"input_index": index, "signature": sig})
                for s in self.contract["vendor_order_confirmation"]["invoice"]["payout"]["signature(s)"]:
                    if s["input_index"] == index:
                        if bitcoin.verify_tx_input(tx, index, redeem_script, s["signature"], vendor_key):
                            tx = bitcoin.apply_multisignatures(tx, index, str(redeem_script),
                                                               sig, str(s["signature"]))
                            valid_inputs += 1
            receipt_json["buyer_receipt"]["receipt"]["payout"] = {}
            if valid_inputs == len(outpoints):
                self.log.info("Broadcasting payout tx %s to network" % bitcoin.txhash(tx))
                self.blockchain.broadcast(tx)
                receipt_json["buyer_receipt"]["receipt"]["payout"]["txid"] = bitcoin.txhash(tx)
            receipt_json["buyer_receipt"]["receipt"]["payout"]["signature(s)"] = signatures
            receipt_json["buyer_receipt"]["receipt"]["payout"]["value"] = value
        if claim:
            receipt_json["buyer_receipt"]["receipt"]["dispute"]["claim"] = claim
        receipt = json.dumps(receipt_json["buyer_receipt"]["receipt"], indent=4)
        receipt_json["buyer_receipt"]["signature"] = \
            self.keychain.signing_key.sign(receipt, encoder=nacl.encoding.HexEncoder)[:128]
        self.contract["buyer_receipt"] = receipt_json["buyer_receipt"]