示例#1
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('all makers have sent their signatures')
		for index, ins in enumerate(self.latest_tx['ins']):
			#remove placeholders
			if ins['script'] == 'deadbeef':
				ins['script'] = ''
		if self.finishcallback != None:
			self.finishcallback(self)
示例#2
0
    def reorder_sigs( self, sigs ):
        reorderedSigs = []
        stx = bitcoin.serialize( self.tx )
        for pub in self.pubs:
            for sig in sigs:
                if bitcoin.verify_tx_input( stx, 0, self.redeemScript, sig, pub ):
                    reorderedSigs.append( sig )
                    break

        return reorderedSigs
示例#3
0
	def add_signature(self, sigb64):
		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
				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
		debug('the entire tx is signed, ready to pushtx()')
		txhex = btc.serialize(self.latest_tx)
		debug('\n' + txhex)

		#TODO send to a random maker or push myself
		#self.msgchan.push_tx(self.active_orders.keys()[0], txhex)	
		self.txid = common.bc_interface.pushtx(txhex)
		debug('pushed tx ' + str(self.txid))
		if self.txid == None:
			debug('unable to pushtx')
		if self.finishcallback != None:
			self.finishcallback(self)
示例#4
0
    def add_signature(self, sigb64):
        sig = base64.b64decode(sigb64).encode('hex')
        inserted_sig = False
        tx = btc.serialize(self.latest_tx)
        for index, ins in enumerate(self.latest_tx['ins']):
            if ins['script'] != '':
                continue
            utxo = ins['outpoint']['hash'] + ':' + str(
                ins['outpoint']['index'])
            utxo_data = common.bc_interface.query_utxo_set(utxo)
            if utxo_data[0] == None:
                continue
            sig_good = btc.verify_tx_input(tx, index, utxo_data[0]['script'],
                                           *btc.deserialize_script(sig))
            if sig_good:
                debug('found good sig at index=%d' % (index))
                ins['script'] = sig
                inserted_sig = True
                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
        debug('the entire tx is signed, ready to pushtx()')
        txhex = btc.serialize(self.latest_tx)
        debug('\n' + txhex)

        #TODO send to a random maker or push myself
        #self.msgchan.push_tx(self.active_orders.keys()[0], txhex)
        txid = common.bc_interface.pushtx(txhex)
        debug('pushed tx ' + str(txid))
        if self.finishcallback != None:
            self.finishcallback(self)
示例#5
0
	def add_signature(self, sigb64):
		sig = base64.b64decode(sigb64).encode('hex')
		inserted_sig = False
		tx = btc.serialize(self.latest_tx)
		for index, ins in enumerate(self.latest_tx['ins']):
			if ins['script'] != '':
				continue
			utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index'])
			utxo_data = common.bc_interface.query_utxo_set(utxo)
			if utxo_data[0] == None:
				continue
			sig_good = btc.verify_tx_input(tx, index, utxo_data[0]['script'], *btc.deserialize_script(sig))
			if sig_good:
				debug('found good sig at index=%d' % (index))
				ins['script'] = sig
				inserted_sig = True
				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
		debug('the entire tx is signed, ready to pushtx()')
		txhex = btc.serialize(self.latest_tx)
		debug('\n' + txhex)

		#TODO send to a random maker or push myself
		#self.msgchan.push_tx(self.active_orders.keys()[0], txhex)	
		txid = common.bc_interface.pushtx(txhex)
		debug('pushed tx ' + str(txid))
		if self.finishcallback != None:
			self.finishcallback(self)
示例#6
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('all makers have sent their signatures')
        for index, ins in enumerate(self.latest_tx['ins']):
            #remove placeholders
            if ins['script'] == 'deadbeef':
                ins['script'] = ''
        if self.finishcallback != None:
            self.finishcallback(self)
示例#7
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)
示例#8
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"]
示例#9
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)
示例#10
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"]