Example #1
0
    def release_funds(self, order_id):
        """
        This function should be called to release funds from a disputed contract after
        the moderator has resolved the dispute and provided his signature.
        """
        if os.path.exists(DATA_FOLDER + "purchases/in progress/" + order_id + ".json"):
            file_path = DATA_FOLDER + "purchases/trade receipts/" + order_id + ".json"
            outpoints = pickle.loads(self.db.Purchases().get_outpoint(order_id))
        elif os.path.exists(DATA_FOLDER + "store/contracts/in progress/" + order_id + ".json"):
            file_path = DATA_FOLDER + "store/contracts/in progress/" + order_id + ".json"
            outpoints = pickle.loads(self.db.Sales().get_outpoint(order_id))

        with open(file_path, 'r') as filename:
            contract = json.load(filename, object_pairs_hook=OrderedDict)

        vendor_address = contract["vendor_order_confirmation"]["invoice"]["payout"]["address"]
        buyer_address = contract["buyer_order"]["order"]["refund_address"]

        for moderator in contract["vendor_offer"]["listing"]["moderators"]:
            if moderator["guid"] == contract["buyer_order"]["order"]["moderator"]:
                masterkey_m = moderator["pubkeys"]["bitcoin"]["key"]

        outputs = []

        outputs.append({'value': contract["dispute_resolution"]["resolution"]["moderator_fee"],
                        'address': contract["dispute_resolution"]["resolution"]["moderator_address"]})

        if "buyer_payout" in contract["dispute_resolution"]["resolution"]:
            outputs.append({'value': contract["dispute_resolution"]["resolution"]["buyer_payout"],
                            'address': buyer_address})

        if "vendor_payout" in contract["dispute_resolution"]["resolution"]:
            outputs.append({'value': contract["dispute_resolution"]["resolution"]["vendor_payout"],
                            'address': vendor_address})

        tx = bitcointools.mktx(outpoints, outputs)
        signatures = []
        chaincode = contract["buyer_order"]["order"]["payment"]["chaincode"]
        redeem_script = str(contract["buyer_order"]["order"]["payment"]["redeem_script"])
        masterkey = bitcointools.bip32_extract_key(KeyChain(self.db).bitcoin_master_privkey)
        childkey = derive_childkey(masterkey, chaincode, bitcointools.MAINNET_PRIVATE)

        mod_key = derive_childkey(masterkey_m, chaincode)

        valid_inputs = 0
        for index in range(0, len(outpoints)):
            sig = bitcointools.multisign(tx, index, redeem_script, childkey)
            signatures.append({"input_index": index, "signature": sig})
            for s in contract["dispute_resolution"]["resolution"]["tx_signatures"]:
                if s["input_index"] == index:
                    if bitcointools.verify_tx_input(tx, index, redeem_script, s["signature"], mod_key):
                        tx = bitcointools.apply_multisignatures(tx, index, str(redeem_script),
                                                                sig, str(s["signature"]))
                        valid_inputs += 1

        if valid_inputs == len(outpoints):
            self.log.info("Broadcasting payout tx %s to network" % bitcointools.txhash(tx))
            self.protocol.multiplexer.blockchain.broadcast(tx)
        else:
            raise Exception("Failed to reconstruct transaction with moderator signature.")
Example #2
0
 def rpc_order(self, sender, pubkey, encrypted):
     try:
         box = Box(PrivateKey(self.signing_key.encode(nacl.encoding.RawEncoder)), PublicKey(pubkey))
         order = box.decrypt(encrypted)
         c = Contract(self.db, contract=json.loads(order, object_pairs_hook=OrderedDict),
                      testnet=self.multiplexer.testnet)
         if c.verify(sender.signed_pubkey[64:]):
             self.router.addContact(sender)
             self.log.info("received an order from %s, waiting for payment..." % sender)
             payment_address = c.contract["buyer_order"]["order"]["payment"]["address"]
             chaincode = c.contract["buyer_order"]["order"]["payment"]["chaincode"]
             masterkey_b = c.contract["buyer_order"]["order"]["id"]["pubkeys"]["bitcoin"]
             buyer_key = derive_childkey(masterkey_b, chaincode)
             amount = c.contract["buyer_order"]["order"]["payment"]["amount"]
             listing_hash = c.contract["buyer_order"]["order"]["ref_hash"]
             signature = self.signing_key.sign(
                 str(payment_address) + str(amount) + str(listing_hash) + str(buyer_key))[:64]
             c.await_funding(self.get_notification_listener(), self.multiplexer.blockchain, signature, False)
             return [signature]
         else:
             self.log.warning("received invalid order from %s" % sender)
             return ["False"]
     except Exception:
         self.log.error("unable to decrypt order from %s" % sender)
         return ["False"]
Example #3
0
 def rpc_order(self, sender, pubkey, encrypted):
     try:
         box = Box(self.signing_key.to_curve25519_private_key(), PublicKey(pubkey))
         order = box.decrypt(encrypted)
         c = Contract(self.db, contract=json.loads(order, object_pairs_hook=OrderedDict),
                      testnet=self.multiplexer.testnet)
         v = c.verify(sender.pubkey)
         if v is True:
             self.router.addContact(sender)
             self.log.info("received an order from %s, waiting for payment..." % sender)
             payment_address = c.contract["buyer_order"]["order"]["payment"]["address"]
             chaincode = c.contract["buyer_order"]["order"]["payment"]["chaincode"]
             masterkey_b = c.contract["buyer_order"]["order"]["id"]["pubkeys"]["bitcoin"]
             buyer_key = derive_childkey(masterkey_b, chaincode)
             amount = c.contract["buyer_order"]["order"]["payment"]["amount"]
             listing_hash = c.contract["vendor_offer"]["listing"]["contract_id"]
             signature = self.signing_key.sign(
                 str(payment_address) + str(amount) + str(listing_hash) + str(buyer_key))[:64]
             c.await_funding(self.get_notification_listener(), self.multiplexer.blockchain, signature, False)
             return [signature]
         else:
             self.log.warning("received invalid order from %s reason %s" % (sender, v))
             return ["False"]
     except Exception, e:
         self.log.error("Exception (%s) occurred processing order from %s" % (e.message, sender))
         return ["False"]
Example #4
0
 def rpc_order(self, sender, pubkey, encrypted):
     try:
         box = Box(self.signing_key.to_curve25519_private_key(), PublicKey(pubkey))
         order = box.decrypt(encrypted)
         c = Contract(self.db, contract=json.loads(order, object_pairs_hook=OrderedDict),
                      testnet=self.multiplexer.testnet)
         if c.verify(sender.pubkey):
             self.router.addContact(sender)
             self.log.info("received an order from %s, waiting for payment..." % sender)
             payment_address = c.contract["buyer_order"]["order"]["payment"]["address"]
             chaincode = c.contract["buyer_order"]["order"]["payment"]["chaincode"]
             masterkey_b = c.contract["buyer_order"]["order"]["id"]["pubkeys"]["bitcoin"]
             buyer_key = derive_childkey(masterkey_b, chaincode)
             amount = c.contract["buyer_order"]["order"]["payment"]["amount"]
             listing_hash = c.contract["vendor_offer"]["listing"]["contract_id"]
             signature = self.signing_key.sign(
                 str(payment_address) + str(amount) + str(listing_hash) + str(buyer_key))[:64]
             c.await_funding(self.get_notification_listener(), self.multiplexer.blockchain, signature, False)
             return [signature]
         else:
             self.log.warning("received invalid order from %s" % sender)
             return ["False"]
     except Exception:
         self.log.error("unable to decrypt order from %s" % sender)
         return ["False"]
Example #5
0
 def parse_response(response):
     try:
         address = contract.contract["buyer_order"]["order"]["payment"]["address"]
         chaincode = contract.contract["buyer_order"]["order"]["payment"]["chaincode"]
         masterkey_b = contract.contract["buyer_order"]["order"]["id"]["pubkeys"]["bitcoin"]
         buyer_key = derive_childkey(masterkey_b, chaincode)
         amount = contract.contract["buyer_order"]["order"]["payment"]["amount"]
         listing_hash = contract.contract["vendor_offer"]["listing"]["contract_id"]
         verify_key = nacl.signing.VerifyKey(node_to_ask.pubkey)
         verify_key.verify(str(address) + str(amount) + str(listing_hash) + str(buyer_key), response[1][0])
         return response[1][0]
     except Exception:
         return False
Example #6
0
 def parse_response(response):
     try:
         address = contract.contract["buyer_order"]["order"]["payment"]["address"]
         chaincode = contract.contract["buyer_order"]["order"]["payment"]["chaincode"]
         masterkey_b = contract.contract["buyer_order"]["order"]["id"]["pubkeys"]["bitcoin"]
         buyer_key = derive_childkey(masterkey_b, chaincode)
         amount = contract.contract["buyer_order"]["order"]["payment"]["amount"]
         listing_hash = contract.contract["buyer_order"]["order"]["ref_hash"]
         verify_key = nacl.signing.VerifyKey(node_to_ask.pubkey)
         verify_key.verify(
             str(address) + str(amount) + str(listing_hash) + str(buyer_key), response[1][0])
         return response[1][0]
     except Exception:
         return False
Example #7
0
            def history_fetched(ec, history):
                outpoints = []
                satoshis = 0
                outputs = []
                dispute_json = {"dispute_resolution": {"resolution": {}}}
                if ec:
                    print ec
                else:
                    for tx_type, txid, i, height, value in history:  # pylint: disable=W0612
                        if tx_type == obelisk.PointIdent.Output:
                            satoshis += value
                            outpoint = txid.encode("hex") + ":" + str(i)
                            if outpoint not in outpoints:
                                outpoints.append(outpoint)

                    satoshis -= TRANSACTION_FEE
                    moderator_fee = round(float(moderator_percentage * satoshis))
                    satoshis -= moderator_fee

                    outputs.append({'value': moderator_fee, 'address': moderator_address})
                    dispute_json["dispute_resolution"]["resolution"]["moderator_address"] = moderator_address
                    dispute_json["dispute_resolution"]["resolution"]["moderator_fee"] = moderator_fee
                    dispute_json["dispute_resolution"]["resolution"]["transaction_fee"] = TRANSACTION_FEE
                    if float(buyer_percentage) > 0:
                        amt = round(float(buyer_percentage * satoshis))
                        dispute_json["dispute_resolution"]["resolution"]["buyer_payout"] = amt
                        outputs.append({'value': amt,
                                        'address': buyer_address})
                    if float(vendor_percentage) > 0:
                        amt = round(float(vendor_percentage * satoshis))
                        dispute_json["dispute_resolution"]["resolution"]["vendor_payout"] = amt
                        outputs.append({'value': amt,
                                        'address': vendor_address})
                    tx = bitcointools.mktx(outpoints, outputs)
                    chaincode = contract["buyer_order"]["order"]["payment"]["chaincode"]
                    redeem_script = str(contract["buyer_order"]["order"]["payment"]["redeem_script"])
                    masterkey_m = bitcointools.bip32_extract_key(KeyChain(self.db).bitcoin_master_privkey)
                    moderator_priv = derive_childkey(masterkey_m, chaincode, bitcointools.MAINNET_PRIVATE)
                    signatures = []
                    for index in range(0, len(outpoints)):
                        sig = bitcointools.multisign(tx, index, redeem_script, moderator_priv)
                        signatures.append({"input_index": index, "signature": sig})
                    dispute_json["dispute_resolution"]["resolution"]["order_id"] = order_id
                    dispute_json["dispute_resolution"]["resolution"]["tx_signatures"] = signatures
                    dispute_json["dispute_resolution"]["resolution"]["claim"] = self.db.Cases().get_claim(order_id)
                    dispute_json["dispute_resolution"]["resolution"]["decision"] = resolution
                    dispute_json["dispute_resolution"]["signature"] = \
                        base64.b64encode(KeyChain(self.db).signing_key.sign(json.dumps(
                            dispute_json["dispute_resolution"]["resolution"]))[:64])

                    def get_node(node_to_ask, recipient_guid, public_key):
                        def parse_response(response):
                            if not response[0]:
                                self.send_message(Node(unhexlify(recipient_guid)),
                                                  public_key.encode(),
                                                  objects.PlaintextMessage.Type.Value("DISPUTE_CLOSE"),
                                                  dispute_json,
                                                  order_id,
                                                  store_only=True)

                        if node_to_ask:
                            skephem = PrivateKey.generate()
                            pkephem = skephem.public_key.encode(nacl.encoding.RawEncoder)
                            box = Box(skephem, public_key)
                            nonce = nacl.utils.random(Box.NONCE_SIZE)
                            ciphertext = box.encrypt(json.dumps(dispute_json, indent=4), nonce)
                            d = self.protocol.callDisputeClose(node_to_ask, pkephem, ciphertext)
                            return d.addCallback(parse_response)
                        else:
                            return parse_response([False])

                    self.kserver.resolve(unhexlify(vendor_guid)).addCallback(get_node, vendor_guid, vendor_enc_key)
                    self.kserver.resolve(unhexlify(buyer_guid)).addCallback(get_node, buyer_guid, buyer_enc_key)
                    self.db.Cases().update_status(order_id, 1)