def on_add_button_clicked( self, widget, data=None ):
        redeem_script = None
        address = None

        try: 
             redeem_script = self.redeem_script_window.script_entry.get_text()
             address = bitcoin.scriptaddr( redeem_script )
             KeyHelper.parse_redeem_script( redeem_script )
        except ValueError as e:
            confirm = gtk.MessageDialog( self.keys_window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "Invalid redeemScript!" )
            confirm.format_secondary_markup(str(e))
            confirm.run()
            confirm.destroy()
            return

        notes = self.redeem_script_window.notes_entry.get_text()

        try:
            self.script_info = KeyHelper.add_redeem_script( redeem_script, notes )
        except ValueError as e:
            confirm = gtk.MessageDialog( self.redeem_script_window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "Duplicate redeemScript!" )
            confirm.format_secondary_markup(str(e))
            confirm.run()
            confirm.destroy()
            return
        except nacl.exceptions.CryptoError:
            confirm = gtk.MessageDialog( self.redeem_script_window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "Invalid Password" )
            confirm.run()
            confirm.destroy()
            return

        self.display_redeem_scripts()
        return True
def create_multisig_address(crypto,m,n,pub_key_list):
    if n!=len(pub_key_list):
        raise Exception('n is not the same as length of pub_key_list') 

    crypto_key_id_list=[]
    for pub_key in pub_key_list:
        c.execute('SELECT * FROM crypto_key WHERE public_key = ?',(pub_key,))
        rows=c.fetchall()
        # create crypto_key entry if public key is not found in database
        if len(rows) ==0:
            c.execute('INSERT INTO crypto_key(crypto,public_key,private_key,encrypted_private_key,timestamp) VALUES(?,?,?,?,?)',
                      (crypto,pub_key,0,0,datetime.datetime.now()))
            crypto_key_id_list.append(c.lastrowid)
            conn.commit()
        else:           
            crypto_key_id_list.append(rows[0][0])
    script=bitcoin.mk_multisig_script(pub_key_list,m)
    address=bitcoin.scriptaddr(script,SCRIPT_HASH_VERSION_BYTE[crypto])
    
    c.execute('INSERT INTO multisig_addr(crypto,address,m,n,timestamp) VALUES(?,?,?,?,?)',
              (crypto,address,m,n,datetime.datetime.now()))
    multisig_addr_id=c.lastrowid 
    conn.commit() 
    #now we need to create multisig_own 
    for crypto_key_id in crypto_key_id_list: 
        c.execute('INSERT INTO multisig_own(crypto_key_id,multisig_addr_id) VALUES(?,?)'
            ,(crypto_key_id,multisig_addr_id))
        conn.commit()

    return address  
Ejemplo n.º 3
0
def test_spend_p2sh_utxos(setup_tx_creation):
    #make a multisig address from 3 privs
    privs = [chr(x) * 32 + '\x01' for x in range(1, 4)]
    pubs = [btc.privkey_to_pubkey(binascii.hexlify(priv)) for priv in privs]
    script = btc.mk_multisig_script(pubs, 2)
    msig_addr = btc.scriptaddr(script, magicbyte=196)
    #pay into it
    wallet = make_wallets(1, [[2, 0, 0, 0, 1]], 3)[0]['wallet']
    jm_single().bc_interface.sync_wallet(wallet)
    amount = 350000000
    ins_full = wallet.select_utxos(0, amount)
    txid = make_sign_and_push(ins_full, wallet, amount, output_addr=msig_addr)
    assert txid
    #wait for mining
    time.sleep(4)
    #spend out; the input can be constructed from the txid of previous
    msig_in = txid + ":0"
    ins = [msig_in]
    #random output address and change addr
    output_addr = wallet.get_new_addr(1, 1)
    amount2 = amount - 50000
    outs = [{'value': amount2, 'address': output_addr}]
    tx = btc.mktx(ins, outs)
    sigs = []
    for priv in privs[:2]:
        sigs.append(btc.multisign(tx, 0, script, binascii.hexlify(priv)))
    tx = btc.apply_multisignatures(tx, 0, script, sigs)
    txid = jm_single().bc_interface.pushtx(tx)
    assert txid
def create_multisig_address(crypto, m, n, pub_key_list):
    if n != len(pub_key_list):
        raise Exception('n is not the same as length of pub_key_list')

    crypto_key_id_list = []
    for pub_key in pub_key_list:
        c.execute('SELECT * FROM crypto_key WHERE public_key = ?', (pub_key, ))
        rows = c.fetchall()
        # create crypto_key entry if public key is not found in database
        if len(rows) == 0:
            c.execute(
                'INSERT INTO crypto_key(crypto,public_key,private_key,encrypted_private_key,timestamp) VALUES(?,?,?,?,?)',
                (crypto, pub_key, 0, 0, datetime.datetime.now()))
            crypto_key_id_list.append(c.lastrowid)
            conn.commit()
        else:
            crypto_key_id_list.append(rows[0][0])
    script = bitcoin.mk_multisig_script(pub_key_list, m)
    address = bitcoin.scriptaddr(script, SCRIPT_HASH_VERSION_BYTE[crypto])

    c.execute(
        'INSERT INTO multisig_addr(crypto,address,m,n,timestamp) VALUES(?,?,?,?,?)',
        (crypto, address, m, n, datetime.datetime.now()))
    multisig_addr_id = c.lastrowid
    conn.commit()
    #now we need to create multisig_own
    for crypto_key_id in crypto_key_id_list:
        c.execute(
            'INSERT INTO multisig_own(crypto_key_id,multisig_addr_id) VALUES(?,?)',
            (crypto_key_id, multisig_addr_id))
        conn.commit()

    return address
Ejemplo n.º 5
0
def main():
    locktime = args.locktime
    privkey = args.privkey
    address = args.address

    script = getRedeemScript(locktime, privkey)
    ins, balance = getBalance(scriptaddr(script, 50))
    len_inputs = len(ins)

    tx = ''

    if balance > 0 and check_addr(address) and is_privkey(privkey):
        # Fee
        fee = round(base_fee + fee_per_input * len_inputs, 8)

        # Outputs
        out_value = int((balance - fee) * COIN)
        outs = [{'address' : address, 'value' : out_value}]

        # Make unsigned transaction
        tx = mktx(ins, outs)

        # Append nLockTime and reset nSequence
        unpacked = deserialize(tx)
        unpacked['locktime'] = locktime
        for i in range(len_inputs):
            unpacked['ins'][i]['sequence'] = 0
        tx = serialize(unpacked)

        # get all signatures
        sigs = []
        for i in range(len_inputs):
            sigs.append(multisign(tx, i, script, privkey))

        # sign inputs
        unpacked = deserialize(tx)
        for i in range(len_inputs):
            unpacked['ins'][i]['script'] = getLen(sigs[i]) + sigs[i]
            unpacked['ins'][i]['script'] += getLen(script) + script
        tx = serialize(unpacked)

    print('> BALANCE (%s): %f' % (scriptaddr(script, 50), balance))

    if len(tx) > 0:
        txid = broadcast(tx)
        print('> RESPONSE: %s' % txid.text)
    def on_script_changed( self, widget, data=None ):
        script = widget.get_text()
        address = None
        try: 
            address = bitcoin.scriptaddr( script )
            KeyHelper.parse_redeem_script( script )
        except Exception as e:
            address = "Invalid Script"

        self.redeem_script_window.address_entry.set_text( address )
        return False
Ejemplo n.º 7
0
    def on_script_changed(self, widget, data=None):
        script = widget.get_text()
        address = None
        try:
            address = bitcoin.scriptaddr(script)
            KeyHelper.parse_redeem_script(script)
        except Exception as e:
            address = "Invalid Script"

        self.redeem_script_window.address_entry.set_text(address)
        return False
Ejemplo n.º 8
0
    def address(self):
        print 'pubkeys', self.pubkeys

        pubkeys = self.pubkeys
        for idx, pubkey in enumerate(pubkeys):
            pubkeys[idx] = pubkey.encode('hex')

        print 'pubkeys2', pubkeys

        script = bitcoin.mk_multisig_script(self.pubkeys, 2, 3)
        address = bitcoin.scriptaddr(script)
        print 'script',script
        return address
Ejemplo n.º 9
0
def main():
    # WIF Private key
    privkey = args.privkey

    if is_privkey(privkey):
        # Block height
        locktime = args.locktime

        redeemscript = getRedeemScript(locktime, privkey)

        # Bitcoin BIP-13 + Litecoin prefix
        p2sh_addr = scriptaddr(redeemscript, 50)

        print('> P2SH ADDRESS: %s' % p2sh_addr)
        print('> REDEEM SCRIPT: %s' % redeemscript)
    else:
        print('> ERROR - PRIVKEY FORMAT')
Ejemplo n.º 10
0
def test_create_p2sh_output_tx(setup_tx_creation, nw, wallet_structures,
                               mean_amt, sdev_amt, amount, pubs, k):
    wallets = make_wallets(nw, wallet_structures, mean_amt, sdev_amt)
    for w in wallets.values():
        jm_single().bc_interface.sync_wallet(w['wallet'])
    for k, w in enumerate(wallets.values()):
        wallet = w['wallet']
        ins_full = wallet.select_utxos(0, amount)
        script = btc.mk_multisig_script(pubs, k)
        #try the alternative argument passing
        pubs.append(k)
        script2 = btc.mk_multisig_script(*pubs)
        assert script2 == script
        output_addr = btc.scriptaddr(script, magicbyte=196)
        txid = make_sign_and_push(ins_full,
                                  wallet,
                                  amount,
                                  output_addr=output_addr)
        assert txid
Ejemplo n.º 11
0
    def on_add_button_clicked(self, widget, data=None):
        redeem_script = None
        address = None

        try:
            redeem_script = self.redeem_script_window.script_entry.get_text()
            address = bitcoin.scriptaddr(redeem_script)
            KeyHelper.parse_redeem_script(redeem_script)
        except ValueError as e:
            confirm = gtk.MessageDialog(
                self.keys_window,
                gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "Invalid redeemScript!")
            confirm.format_secondary_markup(str(e))
            confirm.run()
            confirm.destroy()
            return

        notes = self.redeem_script_window.notes_entry.get_text()

        try:
            self.script_info = KeyHelper.add_redeem_script(
                redeem_script, notes)
        except ValueError as e:
            confirm = gtk.MessageDialog(
                self.redeem_script_window,
                gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "Duplicate redeemScript!")
            confirm.format_secondary_markup(str(e))
            confirm.run()
            confirm.destroy()
            return
        except nacl.exceptions.CryptoError:
            confirm = gtk.MessageDialog(
                self.redeem_script_window,
                gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "Invalid Password")
            confirm.run()
            confirm.destroy()
            return

        self.display_redeem_scripts()
        return True
Ejemplo n.º 12
0
    def add_redeem_script( script, notes ):
        settings = Settings.Instance().get_settings_json()

        if 'redeemScripts' not in settings:
            settings['redeemScripts'] = []

        #check for correctness of redeem_script
        #this will raise an exception if there is a bad script
        KeyHelper.parse_redeem_script( script )

        p2shaddr = bitcoin.scriptaddr( script )

        #see if this is a duplicate
        duplicates = [ dup for dup in settings['redeemScripts'] if dup[0] == p2shaddr ]
        if len( duplicates ) > 0:
            raise ValueError( "%s already in redeem script list!" % p2shaddr )

        settings['redeemScripts'].append( [ p2shaddr, script, notes ] )
        Settings.Instance().save_config_file( settings )

        return settings['redeemScripts']
Ejemplo n.º 13
0
def main():
    scriptSig = getScriptPubKey(args.solution)
    addrP2SH = scriptaddr(scriptSig, 50)
    solution = b2a_hex(args.solution.encode()).decode('utf-8')

    ins, balance = getBalance(addrP2SH)
    len_inputs = len(ins)

    if balance > 0:
        # Output
        outs = [{'address': args.address, 'value': int(balance * COIN)}]

        # Make unsigned transaction
        tx = mktx(ins, outs)

        # Calculate fee
        size = len(a2b_hex(tx))
        fee = int((size / 1024) * 0.01 * COIN)

        # MAX FEE = 0.1 CHA
        fee = 1e7 if fee > 1e7 else fee

        # sign inputs + apply fee
        unpacked = deserialize(tx)

        for puzzle_input in unpacked['ins']:
            puzzle_input['script'] = getHexLen(solution) + solution
            puzzle_input['script'] += getHexLen(scriptSig) + scriptSig

        unpacked['outs'][0]['value'] -= fee

        tx = serialize(unpacked)

        if len(tx) > 0:
            txid = broadcast(tx)
            print('> Transaction broadcasted, %s' % tx)
    else:
        print('> No funds :C')
Ejemplo n.º 14
0
    def add_redeem_script(script, notes):
        settings = Settings.Instance().get_settings_json()

        if 'redeemScripts' not in settings:
            settings['redeemScripts'] = []

        #check for correctness of redeem_script
        #this will raise an exception if there is a bad script
        KeyHelper.parse_redeem_script(script)

        p2shaddr = bitcoin.scriptaddr(script)

        #see if this is a duplicate
        duplicates = [
            dup for dup in settings['redeemScripts'] if dup[0] == p2shaddr
        ]
        if len(duplicates) > 0:
            raise ValueError("%s already in redeem script list!" % p2shaddr)

        settings['redeemScripts'].append([p2shaddr, script, notes])
        Settings.Instance().save_config_file(settings)

        return settings['redeemScripts']
Ejemplo n.º 15
0
    def on_release_funds_tx(self, msg):
        self.log.info('Receiving signed tx from buyer')

        buyer_order_id = "%s-%s" % (msg['senderGUID'], msg['buyer_order_id'])
        order = self.market.orders.get_order(buyer_order_id, by_buyer_id=True)
        contract = order['signed_contract_body']

        # Find Seller Data in Contract
        offer_data = ''.join(contract.split('\n')[8:])
        index_of_seller_signature = offer_data.find(
            '- - -----BEGIN PGP SIGNATURE-----', 0, len(offer_data))
        offer_data_json = offer_data[0:index_of_seller_signature]
        offer_data_json = json.loads(offer_data_json)
        self.log.info('Offer Data: %s', offer_data_json)

        # Find Buyer Data in Contract
        bid_data_index = offer_data.find('"Buyer"', index_of_seller_signature,
                                         len(offer_data))
        end_of_bid_index = offer_data.find('- -----BEGIN PGP SIGNATURE',
                                           bid_data_index, len(offer_data))
        bid_data_json = "{"
        bid_data_json += offer_data[bid_data_index:end_of_bid_index]
        bid_data_json = json.loads(bid_data_json)

        # Find Notary Data in Contract
        notary_data_index = offer_data.find('"Notary"', end_of_bid_index,
                                            len(offer_data))
        end_of_notary_index = offer_data.find('-----BEGIN PGP SIGNATURE',
                                              notary_data_index,
                                              len(offer_data))
        notary_data_json = "{"
        notary_data_json += offer_data[notary_data_index:end_of_notary_index]
        notary_data_json = json.loads(notary_data_json)
        self.log.info('Notary Data: %s', notary_data_json)

        try:
            client = obelisk.ObeliskOfLightClient(
                'tcp://obelisk.coinkite.com:9091')

            script = msg['script']
            tx = msg['tx']
            multi_addr = scriptaddr(script)

            def cb(ec, history, order):
                if ec is not None:
                    self.log.error("Error fetching history: %s", ec)
                    # TODO: Send error message to GUI
                    return

                unspent = [row[:4] for row in history if row[4] is None]

                # Send all unspent outputs (everything in the address) minus
                # the fee
                inputs = []
                for row in unspent:
                    assert len(row) == 4
                    inputs.append(
                        str(row[0].encode('hex')) + ":" + str(row[1]))

                seller_signatures = []
                print 'private key ', self.transport.settings['privkey']
                for x in range(0, len(inputs)):
                    ms = multisign(tx, x, script,
                                   self.transport.settings['privkey'])
                    print 'seller sig', ms
                    seller_signatures.append(ms)

                tx2 = apply_multisignatures(tx, 0, script,
                                            seller_signatures[0],
                                            msg['signatures'][0])

                print 'FINAL SCRIPT: %s' % tx2
                print 'Sent', eligius_pushtx(tx2)

                self.send_to_client(
                    None, {
                        "type": "order_notify",
                        "msg": "Funds were released for your sale."
                    })

            def get_history():
                client.fetch_history(
                    multi_addr,
                    lambda ec, history, order=order: cb(ec, history, order))

            reactor.callFromThread(get_history)

        except Exception as e:
            self.log.error('%s', e)
Ejemplo n.º 16
0
    def client_release_payment(self, socket_handler, msg):
        self.log.info('Releasing payment to Merchant %s', msg)

        order = self.market.orders.get_order(msg['orderId'])
        contract = order['signed_contract_body']

        # Find Seller Data in Contract
        offer_data = ''.join(contract.split('\n')[8:])
        index_of_seller_signature = offer_data.find(
            '- - -----BEGIN PGP SIGNATURE-----', 0, len(offer_data))
        offer_data_json = offer_data[0:index_of_seller_signature]
        offer_data_json = json.loads(offer_data_json)
        self.log.info('Offer Data: %s', offer_data_json)

        # Find Buyer Data in Contract
        bid_data_index = offer_data.find('"Buyer"', index_of_seller_signature,
                                         len(offer_data))
        end_of_bid_index = offer_data.find('- -----BEGIN PGP SIGNATURE',
                                           bid_data_index, len(offer_data))
        bid_data_json = "{"
        bid_data_json += offer_data[bid_data_index:end_of_bid_index]
        bid_data_json = json.loads(bid_data_json)

        # Find Notary Data in Contract
        notary_data_index = offer_data.find('"Notary"', end_of_bid_index,
                                            len(offer_data))
        end_of_notary_index = offer_data.find('-----BEGIN PGP SIGNATURE',
                                              notary_data_index,
                                              len(offer_data))
        notary_data_json = "{"
        notary_data_json += offer_data[notary_data_index:end_of_notary_index]
        notary_data_json = json.loads(notary_data_json)
        self.log.info('Notary Data: %s', notary_data_json)

        try:
            client = obelisk.ObeliskOfLightClient(
                'tcp://obelisk.coinkite.com:9091')

            seller = offer_data_json['Seller']
            buyer = bid_data_json['Buyer']
            notary = notary_data_json['Notary']

            pubkeys = [
                seller['seller_BTC_uncompressed_pubkey'],
                buyer['buyer_BTC_uncompressed_pubkey'],
                notary['notary_BTC_uncompressed_pubkey']
            ]

            script = mk_multisig_script(pubkeys, 2, 3)
            multi_address = scriptaddr(script)

            def cb(ec, history, order):
                settings = self.market.get_settings()
                private_key = settings.get('privkey')

                if ec is not None:
                    self.log.error("Error fetching history: %s", ec)
                    # TODO: Send error message to GUI
                    return

                # Create unsigned transaction
                unspent = [row[:4] for row in history if row[4] is None]

                # Send all unspent outputs (everything in the address) minus
                # the fee
                total_amount = 0
                inputs = []
                for row in unspent:
                    assert len(row) == 4
                    inputs.append(
                        str(row[0].encode('hex')) + ":" + str(row[1]))
                    value = row[3]
                    total_amount += value

                # Constrain fee so we don't get negative amount to send
                fee = min(total_amount, 10000)
                send_amount = total_amount - fee

                payment_output = order['payment_address']
                tx = mktx(inputs,
                          [str(payment_output) + ":" + str(send_amount)])

                signatures = []
                for x in range(0, len(inputs)):
                    ms = multisign(tx, x, script, private_key)
                    signatures.append(ms)

                print signatures

                self.market.release_funds_to_merchant(buyer['buyer_order_id'],
                                                      tx, script, signatures,
                                                      order.get('merchant'))

            def get_history():
                client.fetch_history(
                    multi_address,
                    lambda ec, history, order=order: cb(ec, history, order))

            reactor.callFromThread(get_history)

        except Exception as e:
            self.log.error('%s', e)
Ejemplo n.º 17
0
    def get_order(self, order_id, by_buyer_id=False):

        notary_fee = ""

        if not by_buyer_id:
            _order = self.db_connection.select_entries("orders", {"order_id": order_id})[0]
        else:
            _order = self.db_connection.select_entries("orders", {"buyer_order_id": order_id})[0]
        total_price = 0

        offer_data_json = self.get_offer_json(_order['signed_contract_body'], _order['state'])
        buyer_data_json = self.get_buyer_json(_order['signed_contract_body'], _order['state'])

        if _order['state'] != Orders.State.SENT:
            notary_json = self.get_notary_json(_order['signed_contract_body'], _order['state'])
            notary = notary_json['Notary']['notary_GUID']
        else:
            notary = ""

        if _order['state'] in (Orders.State.NEED_TO_PAY,
                               Orders.State.NOTARIZED,
                               Orders.State.WAITING_FOR_PAYMENT,
                               Orders.State.WAITING_FOR_MERCHANT,
                               Orders.State.PAID,
                               Orders.State.BUYER_PAID,
                               Orders.State.SHIPPED,
                               Orders.State.COMPLETED):

            def send_to_client_callback(total):
                if self.transport.handler is not None:
                    self.transport.handler.send_to_client(None, {"type": "order_payment_amount",
                                                                 "order_id": order_id,
                                                                 "value": total})

            pubkeys = [
                offer_data_json['Seller']['seller_BTC_uncompressed_pubkey'],
                buyer_data_json['Buyer']['buyer_BTC_uncompressed_pubkey'],
                notary_json['Notary']['notary_BTC_uncompressed_pubkey']
            ]

            script = mk_multisig_script(pubkeys, 2, 3)
            payment_address = scriptaddr(script)

            def get_unspent():
                trust.get_unspent(payment_address, send_to_client_callback)

            threading.Thread(target=get_unspent).start()

            if 'shipping_price' in _order:
                shipping_price = _order['shipping_price'] if _order['shipping_price'] != '' else 0
            else:
                shipping_price = 0

            try:
                total_price = str((Decimal(shipping_price) + Decimal(_order['item_price']))) \
                    if 'item_price' in _order else _order['item_price']
            except Exception as exc:
                self.log.error('Probably not a number %s', exc)

            notary_fee = notary_json['Notary']['notary_fee']

        # Generate QR code
        qr_code = self.get_qr_code(offer_data_json['Contract']['item_title'], _order['address'], total_price)
        merchant_bitmessage = offer_data_json.get('Seller', '').get('seller_Bitmessage')
        buyer_bitmessage = buyer_data_json.get('Buyer', '').get('buyer_Bitmessage')

        self.log.debug('Shipping Address: %s', _order.get('shipping_address'))
        if _order.get('buyer') == self.transport.guid:
            shipping_address = self.get_shipping_address()
        else:
            shipping_address = _order.get('shipping_address')

        # Get order prototype object before storing
        order = {"id": _order['id'],
                 "state": _order.get('state'),
                 "address": _order.get('address'),
                 "buyer": _order.get('buyer'),
                 "merchant": _order.get('merchant'),
                 "order_id": _order.get('order_id'),
                 "item_quantity": _order.get('item_quantity'),
                 "item_price": _order.get('item_price'),
                 "shipping_price": _order.get('shipping_price'),
                 "shipping_address": shipping_address,
                 "total_price": total_price,
                 "merchant_bitmessage": merchant_bitmessage,
                 "buyer_bitmessage": buyer_bitmessage,
                 "notary": notary,
                 "notary_fee": notary_fee,
                 "payment_address": _order.get('payment_address'),
                 "payment_address_amount": _order.get('payment_address_amount'),
                 "qrcode": 'data:image/png;base64,' + qr_code,
                 "item_title": offer_data_json['Contract']['item_title'],
                 "item_desc": offer_data_json['Contract']['item_desc'],
                 "signed_contract_body": _order.get('signed_contract_body'),
                 "note_for_merchant": _order.get('note_for_merchant'),
                 "merchant_tx": _order.get('merchant_tx'),
                 "merchant_sigs": _order.get('merchant_sigs'),
                 "merchant_script": _order.get('merchant_script'),
                 "updated": _order.get('updated')}

        if len(offer_data_json['Contract']['item_remote_images']):
            order['item_images'] = offer_data_json['Contract']['item_remote_images']
        else:
            order['item_images'] = []

        self.log.datadump('FULL ORDER: %s', order)

        return order
Ejemplo n.º 18
0
    def on_release_funds_tx(self, msg):
        self.log.info('Receiving signed tx from buyer')

        buyer_order_id = "%s-%s" % (msg['senderGUID'], msg['buyer_order_id'])
        order = self.market.orders.get_order(buyer_order_id, by_buyer_id=True)
        contract = order['signed_contract_body']

        # Find Seller Data in Contract
        offer_data = ''.join(contract.split('\n')[8:])
        index_of_seller_signature = offer_data.find(
            '- - -----BEGIN PGP SIGNATURE-----', 0, len(offer_data)
        )
        offer_data_json = offer_data[0:index_of_seller_signature]
        offer_data_json = json.loads(offer_data_json)
        self.log.info('Offer Data: %s', offer_data_json)

        # Find Buyer Data in Contract
        bid_data_index = offer_data.find(
            '"Buyer"', index_of_seller_signature, len(offer_data)
        )
        end_of_bid_index = offer_data.find(
            '- -----BEGIN PGP SIGNATURE', bid_data_index, len(offer_data)
        )
        bid_data_json = "{"
        bid_data_json += offer_data[bid_data_index:end_of_bid_index]
        bid_data_json = json.loads(bid_data_json)

        # Find Notary Data in Contract
        notary_data_index = offer_data.find(
            '"Notary"', end_of_bid_index, len(offer_data)
        )
        end_of_notary_index = offer_data.find(
            '-----BEGIN PGP SIGNATURE', notary_data_index, len(offer_data)
        )
        notary_data_json = "{"
        notary_data_json += offer_data[notary_data_index:end_of_notary_index]
        notary_data_json = json.loads(notary_data_json)
        self.log.info('Notary Data: %s', notary_data_json)

        try:
            client = obelisk.ObeliskOfLightClient(
                'tcp://obelisk.coinkite.com:9091'
            )

            script = msg['script']
            tx = msg['tx']
            multi_addr = scriptaddr(script)

            def cb(ec, history, order):
                if ec is not None:
                    self.log.error("Error fetching history: %s", ec)
                    # TODO: Send error message to GUI
                    return

                unspent = [row[:4] for row in history if row[4] is None]

                # Send all unspent outputs (everything in the address) minus
                # the fee
                inputs = []
                for row in unspent:
                    assert len(row) == 4
                    inputs.append(
                        str(row[0].encode('hex')) + ":" + str(row[1])
                    )

                seller_signatures = []
                print 'private key ', self.transport.settings['privkey']
                for x in range(0, len(inputs)):
                    ms = multisign(
                        tx, x, script, self.transport.settings['privkey']
                    )
                    print 'seller sig', ms
                    seller_signatures.append(ms)

                tx2 = apply_multisignatures(
                    tx, 0, script, seller_signatures[0], msg['signatures'][0]
                )

                print 'FINAL SCRIPT: %s' % tx2
                print 'Sent', eligius_pushtx(tx2)

                self.send_to_client(
                    None,
                    {
                        "type": "order_notify",
                        "msg": "Funds were released for your sale."
                    }
                )

            def get_history():
                client.fetch_history(
                    multi_addr,
                    lambda ec, history, order=order: cb(ec, history, order)
                )

            reactor.callFromThread(get_history)

        except Exception as e:
            self.log.error('%s', e)
Ejemplo n.º 19
0
    def client_release_payment(self, socket_handler, msg):
        self.log.info('Releasing payment to Merchant %s', msg)

        order = self.market.orders.get_order(msg['orderId'])
        contract = order['signed_contract_body']

        # Find Seller Data in Contract
        offer_data = ''.join(contract.split('\n')[8:])
        index_of_seller_signature = offer_data.find(
            '- - -----BEGIN PGP SIGNATURE-----', 0, len(offer_data)
        )
        offer_data_json = offer_data[0:index_of_seller_signature]
        offer_data_json = json.loads(offer_data_json)
        self.log.info('Offer Data: %s', offer_data_json)

        # Find Buyer Data in Contract
        bid_data_index = offer_data.find(
            '"Buyer"', index_of_seller_signature, len(offer_data)
        )
        end_of_bid_index = offer_data.find(
            '- -----BEGIN PGP SIGNATURE', bid_data_index, len(offer_data)
        )
        bid_data_json = "{"
        bid_data_json += offer_data[bid_data_index:end_of_bid_index]
        bid_data_json = json.loads(bid_data_json)

        # Find Notary Data in Contract
        notary_data_index = offer_data.find(
            '"Notary"', end_of_bid_index, len(offer_data)
        )
        end_of_notary_index = offer_data.find(
            '-----BEGIN PGP SIGNATURE', notary_data_index, len(offer_data)
        )
        notary_data_json = "{"
        notary_data_json += offer_data[notary_data_index:end_of_notary_index]
        notary_data_json = json.loads(notary_data_json)
        self.log.info('Notary Data: %s', notary_data_json)

        try:
            client = obelisk.ObeliskOfLightClient(
                'tcp://obelisk.coinkite.com:9091'
            )

            seller = offer_data_json['Seller']
            buyer = bid_data_json['Buyer']
            notary = notary_data_json['Notary']

            pubkeys = [
                seller['seller_BTC_uncompressed_pubkey'],
                buyer['buyer_BTC_uncompressed_pubkey'],
                notary['notary_BTC_uncompressed_pubkey']
            ]

            script = mk_multisig_script(pubkeys, 2, 3)
            multi_address = scriptaddr(script)

            def cb(ec, history, order):
                settings = self.market.get_settings()
                private_key = settings.get('privkey')

                if ec is not None:
                    self.log.error("Error fetching history: %s", ec)
                    # TODO: Send error message to GUI
                    return

                # Create unsigned transaction
                unspent = [row[:4] for row in history if row[4] is None]

                # Send all unspent outputs (everything in the address) minus
                # the fee
                total_amount = 0
                inputs = []
                for row in unspent:
                    assert len(row) == 4
                    inputs.append(
                        str(row[0].encode('hex')) + ":" + str(row[1])
                    )
                    value = row[3]
                    total_amount += value

                # Constrain fee so we don't get negative amount to send
                fee = min(total_amount, 10000)
                send_amount = total_amount - fee

                payment_output = order['payment_address']
                tx = mktx(
                    inputs, [str(payment_output) + ":" + str(send_amount)]
                )

                signatures = []
                for x in range(0, len(inputs)):
                    ms = multisign(tx, x, script, private_key)
                    signatures.append(ms)

                print signatures

                self.market.release_funds_to_merchant(
                    buyer['buyer_order_id'],
                    tx, script, signatures,
                    order.get('merchant')
                )

            def get_history():
                client.fetch_history(
                    multi_address,
                    lambda ec, history, order=order: cb(ec, history, order)
                )

            reactor.callFromThread(get_history)

        except Exception as e:
            self.log.error('%s', e)
Ejemplo n.º 20
0
def main():
    scriptpubkey = getScriptPubKey(args.solution)
    addrP2SH = scriptaddr(scriptpubkey, ADDRESS_PREFIX)
    print('> P2SH Address: %s' % addrP2SH)
Ejemplo n.º 21
0
    def handle_notarized_order(self, msg):

        self.log.info('Handling notarized order')

        contract = msg['rawContract']

        # Find Seller Data in Contract
        offer_data = ''.join(contract.split('\n')[8:])
        index_of_seller_signature = offer_data.find('- - -----BEGIN PGP SIGNATURE-----', 0, len(offer_data))
        offer_data_json = offer_data[0:index_of_seller_signature]
        self.log.info('Offer Data: %s', offer_data_json)
        offer_data_json = json.loads(str(offer_data_json))

        # Find Buyer Data in Contract
        bid_data_index = offer_data.find('"Buyer"', index_of_seller_signature, len(offer_data))
        end_of_bid_index = offer_data.find('- -----BEGIN PGP SIGNATURE', bid_data_index, len(offer_data))
        bid_data_json = "{" + offer_data[bid_data_index:end_of_bid_index]
        bid_data_json = json.loads(bid_data_json)
        self.log.info('Bid Data: %s', bid_data_json)

        # Find Notary Data in Contract
        notary_data_index = offer_data.find('"Notary"', end_of_bid_index, len(offer_data))
        end_of_notary_index = offer_data.find('-----BEGIN PGP SIGNATURE', notary_data_index, len(offer_data))
        notary_data_json = "{" + offer_data[notary_data_index:end_of_notary_index]
        notary_data_json = json.loads(notary_data_json)
        self.log.info('Notary Data: %s', notary_data_json)

        # Generate multi-sig address
        pubkeys = [offer_data_json['Seller']['seller_BTC_uncompressed_pubkey'],
                   bid_data_json['Buyer']['buyer_BTC_uncompressed_pubkey'],
                   notary_data_json['Notary']['notary_BTC_uncompressed_pubkey']]
        script = mk_multisig_script(pubkeys, 2, 3)

        multisig_address = scriptaddr(script)

        seller_GUID = offer_data_json['Seller']['seller_GUID']

        order_id = bid_data_json['Buyer']['buyer_order_id']

        contract_key = hashlib.sha1(str(contract)).hexdigest()
        hash_value = hashlib.new('ripemd160')
        hash_value.update(contract_key)
        contract_key = hash_value.hexdigest()

        if seller_GUID == self.transport.guid:
            self.log.info('I am the seller!')
            state = 'Waiting for Payment'

            merchant_order_id = random.randint(0, 1000000)
            while len(self.db.selectEntries("orders", {"id": order_id})) > 0:
                merchant_order_id = random.randint(0, 1000000)

            buyer_id = "%s-%s" % (
                bid_data_json['Buyer']['buyer_GUID'],
                bid_data_json['Buyer']['buyer_order_id']
            )

            self.db.insertEntry(
                "orders",
                {
                    'market_id': self.transport.market_id,
                    'contract_key': contract_key,
                    'order_id': merchant_order_id,
                    'signed_contract_body': str(contract),
                    'state': state,
                    'buyer_order_id': buyer_id,
                    'merchant': offer_data_json['Seller']['seller_GUID'],
                    'buyer': bid_data_json['Buyer']['buyer_GUID'],
                    'notary': notary_data_json['Notary']['notary_GUID'],
                    'address': multisig_address,
                    'shipping_address': self.transport.cryptor.decrypt(
                        bid_data_json['Buyer']['buyer_deliveryaddr'].decode('hex')),
                    'item_price': offer_data_json['Contract'].get('item_price', 0),
                    'shipping_price': offer_data_json['Contract']['item_delivery'].get('shipping_price', 0),
                    'note_for_merchant': bid_data_json['Buyer']['note_for_seller'],
                    "updated": time.time()
                }
            )

            self.transport.handler.send_to_client(None, {"type": "order_notify",
                                                         "msg": "You just received a new order."})

        else:
            self.log.info('I am the buyer')
            state = 'Need to Pay'

            self.db.updateEntries(
                "orders",
                {
                    'market_id': self.transport.market_id,
                    'contract_key': contract_key,
                    'signed_contract_body': str(contract),
                    'state': state,
                    'merchant': offer_data_json['Seller']['seller_GUID'],
                    'buyer': bid_data_json['Buyer']['buyer_GUID'],
                    'notary': notary_data_json['Notary']['notary_GUID'],
                    'address': multisig_address,
                    'shipping_address': json.dumps(self.get_shipping_address()),
                    'item_price': offer_data_json['Contract'].get('item_price', 0),
                    'shipping_price': offer_data_json['Contract']['item_delivery'].get('shipping_price', ''),
                    'note_for_merchant': bid_data_json['Buyer']['note_for_seller'],
                    "updated": time.time()
                },
                {
                    'order_id': order_id
                }
            )

            self.transport.handler.send_to_client(None, {"type": "order_notify",
                                                         "msg": "Your order requires payment now."})
Ejemplo n.º 22
0
    def handle_bid_order(self, bid):

        self.log.info('Bid Order: %s', bid)

        new_peer = self.transport.get_crypto_peer(bid.get('merchantGUID'),
                                                  bid.get('merchantURI'),
                                                  bid.get('merchantPubkey'))

        # Generate unique id for this bid
        order_id = random.randint(0, 1000000)
        while len(self.db.selectEntries("contracts", {"id": order_id})) > 0:
            order_id = random.randint(0, 1000000)

        # Add to contract and sign
        contract = bid.get('rawContract')

        contract_stripped = "".join(contract.split('\n'))

        bidder_pgp_start_index = contract_stripped.find("buyer_pgp", 0, len(contract_stripped))
        bidder_pgp_end_index = contract_stripped.find("buyer_GUID", 0, len(contract_stripped))
        bidder_pgp = contract_stripped[bidder_pgp_start_index + 13:bidder_pgp_end_index]

        self.gpg.import_keys(bidder_pgp)
        v = self.gpg.verify(contract)
        if v:
            self.log.info('Sellers contract verified')

        notary_section = {}

        notary_section['Notary'] = {
            'notary_GUID': self.transport.guid,
            'notary_BTC_uncompressed_pubkey': privkey_to_pubkey(self.transport.settings['privkey']),
            'notary_pgp': self.transport.settings['PGPPubKey'],
            'notary_fee': "",
            'notary_order_id': order_id
        }

        offer_data_json = self.get_offer_json(contract, Orders.State.SENT)
        bid_data_json = self.get_buyer_json(contract, Orders.State.SENT)

        pubkeys = [
            offer_data_json['Seller']['seller_BTC_uncompressed_pubkey'],
            bid_data_json['Buyer']['buyer_BTC_uncompressed_pubkey'],
            privkey_to_pubkey(self.transport.settings['privkey'])
        ]

        script = mk_multisig_script(pubkeys, 2, 3)
        multisig_address = scriptaddr(script)

        notary_section['Escrow'] = {
            'multisig_address': multisig_address,
            'redemption_script': script
        }

        self.log.debug('Notary: %s', notary_section)

        gpg = self.gpg

        # Prepare contract body
        notary_json = json.dumps(notary_section, indent=0)
        seg_len = 52

        out_text = "\n".join(
            notary_json[x:x + seg_len]
            for x in range(0, len(notary_json), seg_len)
        )

        # Append new data to contract
        out_text = "%s\n%s" % (contract, out_text)

        signed_data = gpg.sign(out_text, passphrase='P@ssw0rd',
                               keyid=self.transport.settings.get('PGPPubkeyFingerprint'))

        self.log.debug('Double-signed Contract: %s', signed_data)

        # Hash the contract for storage
        contract_key = hashlib.sha1(str(signed_data)).hexdigest()
        hash_value = hashlib.new('ripemd160')
        hash_value.update(contract_key)
        contract_key = hash_value.hexdigest()

        self.log.info('Order ID: %s', order_id)

        # Push buy order to DHT and node if available
        # self.transport.store(contract_key, str(signed_data), self.transport.guid)
        # self.update_listings_index()

        # Find Seller Data in Contract
        offer_data = ''.join(contract.split('\n')[8:])
        index_of_seller_signature = offer_data.find('- -----BEGIN PGP SIGNATURE-----', 0, len(offer_data))
        offer_data_json = "{\"Seller\": {" + offer_data[0:index_of_seller_signature]
        self.log.info('Offer Data: %s', offer_data_json)
        offer_data_json = json.loads(str(offer_data_json))

        # Find Buyer Data in Contract
        bid_data_index = offer_data.find('"Buyer"', index_of_seller_signature, len(offer_data))
        end_of_bid_index = offer_data.find('-----BEGIN PGP SIGNATURE', bid_data_index, len(offer_data))
        bid_data_json = "{" + offer_data[bid_data_index:end_of_bid_index]
        bid_data_json = json.loads(bid_data_json)
        self.log.info('Bid Data: %s', bid_data_json)

        buyer_order_id = "%s-%s" % (
            bid_data_json['Buyer']['buyer_GUID'],
            bid_data_json['Buyer']['buyer_order_id']
        )

        pubkeys = [
            offer_data_json['Seller']['seller_BTC_uncompressed_pubkey'],
            bid_data_json['Buyer']['buyer_BTC_uncompressed_pubkey'],
            privkey_to_pubkey(self.transport.settings['privkey'])
        ]

        script = mk_multisig_script(pubkeys, 2, 3)
        multisig_address = scriptaddr(script)

        self.db.insertEntry(
            "orders", {
                'market_id': self.transport.market_id,
                'contract_key': contract_key,
                'signed_contract_body': str(signed_data),
                'state': Orders.State.NOTARIZED,
                'buyer_order_id': buyer_order_id,
                'order_id': order_id,
                'merchant': offer_data_json['Seller']['seller_GUID'],
                'buyer': bid_data_json['Buyer']['buyer_GUID'],
                'address': multisig_address,
                'item_price': offer_data_json['Contract'].get('item_price', 0),
                'shipping_price': offer_data_json['Contract']['item_delivery'].get('shipping_price', ""),
                'note_for_merchant': bid_data_json['Buyer']['note_for_seller'],
                "updated": time.time()
            }
        )

        # Send order to seller and buyer
        self.log.info('Sending notarized contract to buyer and seller %s', bid)

        if self.transport.handler is not None:
            self.transport.handler.send_to_client(None, {"type": "order_notify",
                                                         "msg": "You just auto-notarized a contract."})

        notarized_order = {
            "type": "order",
            "state": "Notarized",
            "rawContract": str(signed_data)
        }

        if new_peer is not None:
            new_peer.send(notarized_order)
        self.transport.send(notarized_order, bid_data_json['Buyer']['buyer_GUID'])

        self.log.info('Sent notarized contract to Seller and Buyer')
Ejemplo n.º 23
0
    def get_order(self, order_id, by_buyer_id=False):

        if not by_buyer_id:
            _order = self.db.selectEntries("orders", {"order_id": order_id})[0]
        else:
            _order = self.db.selectEntries("orders", {"buyer_order_id": order_id})[0]
        total_price = 0

        offer_data_json = self.get_offer_json(_order['signed_contract_body'], _order['state'])
        buyer_data_json = self.get_buyer_json(_order['signed_contract_body'], _order['state'])

        if _order['state'] != Orders.State.SENT:
            notary_json = self.get_notary_json(_order['signed_contract_body'], _order['state'])
            notary = notary_json['Notary']['notary_GUID']
        else:
            notary = ""

        if _order['state'] in (Orders.State.NEED_TO_PAY,
                               Orders.State.NOTARIZED,
                               Orders.State.WAITING_FOR_PAYMENT,
                               Orders.State.PAID,
                               Orders.State.BUYER_PAID,
                               Orders.State.SHIPPED):

            def cb(total):
                if self.transport.handler is not None:
                    self.transport.handler.send_to_client(None, {"type": "order_payment_amount",
                                                                 "value": total})

            pubkeys = [
                offer_data_json['Seller']['seller_BTC_uncompressed_pubkey'],
                buyer_data_json['Buyer']['buyer_BTC_uncompressed_pubkey'],
                notary_json['Notary']['notary_BTC_uncompressed_pubkey']
            ]

            script = mk_multisig_script(pubkeys, 2, 3)
            payment_address = scriptaddr(script)

            trust.get_unspent(payment_address, cb)

            if 'shipping_price' in _order:
                shipping_price = _order['shipping_price'] if _order['shipping_price'] != '' else 0
            else:
                shipping_price = 0

            try:
                total_price = str((Decimal(shipping_price) + Decimal(_order['item_price']))) \
                    if 'item_price' in _order else _order['item_price']
            except Exception as e:
                self.log.error('Probably not a number %s', e)

        # Generate QR code
        qr = self.get_qr_code(offer_data_json['Contract']['item_title'], _order['address'], total_price)
        merchant_bitmessage = offer_data_json.get('Seller', '').get('seller_Bitmessage')
        buyer_bitmessage = buyer_data_json.get('Buyer', '').get('buyer_Bitmessage')

        # Get order prototype object before storing
        order = {"id": _order['id'],
                 "state": _order.get('state'),
                 "address": _order.get('address'),
                 "buyer": _order.get('buyer'),
                 "merchant": _order.get('merchant'),
                 "order_id": _order.get('order_id'),
                 "item_price": _order.get('item_price'),
                 "shipping_price": _order.get('shipping_price'),
                 "shipping_address": str(_order.get('shipping_address')),
                 "total_price": total_price,
                 "merchant_bitmessage": merchant_bitmessage,
                 "buyer_bitmessage": buyer_bitmessage,
                 "notary": notary,
                 "payment_address": _order.get('payment_address'),
                 "payment_address_amount": _order.get('payment_address_amount'),
                 "qrcode": 'data:image/png;base64,' + qr,
                 "item_title": offer_data_json['Contract']['item_title'],
                 "signed_contract_body": _order.get('signed_contract_body'),
                 "note_for_merchant": _order.get('note_for_merchant'),
                 "updated": _order.get('updated')}

        if 'item_images' in offer_data_json['Contract'] and offer_data_json['Contract']['item_images'] != {}:
            order['item_image'] = offer_data_json['Contract']['item_images']
        else:
            order['item_image'] = "img/no-photo.png"

        self.log.datadump('FULL ORDER: %s', order)

        return order
Ejemplo n.º 24
0
    def ship_order(self, order, order_id, payment_address):
        self.log.info('Shipping order %s', order)

        del order['qrcode']
        del order['item_images']
        del order['total_price']
        del order['item_title']
        del order['item_desc']
        del order['buyer_bitmessage']
        del order['merchant_bitmessage']
        del order['payment_address_amount']

        order['state'] = Orders.State.SHIPPED
        order['payment_address'] = payment_address
        order['type'] = 'order'
        self.db_connection.update_entries("orders", order, {"order_id": order_id})

        # Find Seller Data in Contract
        offer_data = ''.join(order['signed_contract_body'].split('\n')[8:])
        index_of_seller_signature = offer_data.find('- - -----BEGIN PGP SIGNATURE-----', 0, len(offer_data))
        offer_data_json = offer_data[0:index_of_seller_signature]
        self.log.info('Offer Data: %s', offer_data_json)
        offer_data_json = json.loads(str(offer_data_json))

        # Find Buyer Data in Contract
        self.log.info(offer_data)
        bid_data_index = offer_data.find('"Buyer"', index_of_seller_signature, len(offer_data))
        end_of_bid_index = offer_data.find('- -----BEGIN PGP SIGNATURE', bid_data_index, len(offer_data))
        bid_data_json = "{" + offer_data[bid_data_index:end_of_bid_index]
        bid_data_json = json.loads(bid_data_json)
        self.log.info('Bid Data: %s', bid_data_json)

        # Find Notary Data in Contract
        notary_data_index = offer_data.find(
            '"Notary"', end_of_bid_index, len(offer_data)
        )
        end_of_notary_index = offer_data.find(
            '-----BEGIN PGP SIGNATURE', notary_data_index, len(offer_data)
        )
        notary_data_json = "{"
        notary_data_json += offer_data[notary_data_index:end_of_notary_index]
        notary_data_json = json.loads(notary_data_json)
        self.log.info('Notary Data: %s', notary_data_json)

        # TODO: Check to ensure the OBelisk server is listening first


        try:
            client = obelisk.ObeliskOfLightClient(
                'tcp://%s' % self.transport.settings['obelisk']
            )

            seller = offer_data_json['Seller']
            buyer = bid_data_json['Buyer']
            notary = notary_data_json['Notary']

            pubkeys = [
                seller['seller_BTC_uncompressed_pubkey'],
                buyer['buyer_BTC_uncompressed_pubkey'],
                notary['notary_BTC_uncompressed_pubkey']
            ]

            script = mk_multisig_script(pubkeys, 2, 3)
            multi_address = scriptaddr(script)

            def cb(ec, history, order):

                self.log.debug('Callback for history %s', history)

                private_key = self.get_signing_key(seller['seller_contract_id'])

                if ec is not None:
                    self.log.error("Error fetching history: %s", ec)
                    # TODO: Send error message to GUI
                    return

                # Create unsigned transaction
                unspent = [row[:4] for row in history if row[4] is None]

                # Send all unspent outputs (everything in the address) minus
                # the fee
                total_amount = 0
                inputs = []
                for row in unspent:
                    assert len(row) == 4
                    inputs.append(
                        str(row[0].encode('hex')) + ":" + str(row[1])
                    )
                    value = row[3]
                    total_amount += value

                # Constrain fee so we don't get negative amount to send
                fee = min(total_amount, 10000)
                send_amount = total_amount - fee

                payment_output = order['payment_address']
                tx = mktx(
                    inputs, [str(payment_output) + ":" + str(send_amount)]
                )

                # Sign all the inputs
                signatures = []
                for x in range(0, len(inputs)):
                    ms = multisign(tx, x, script, private_key)
                    signatures.append(ms)

                self.log.debug('Merchant TX Signatures: %s', signatures)

                order['merchant_tx'] = tx
                order['merchant_script'] = script
                order['buyer_order_id'] = buyer['buyer_order_id']
                order['merchant_sigs'] = signatures

                self.transport.send(order, bid_data_json['Buyer']['buyer_GUID'])

            def get_history():
                self.log.debug('Getting history')

                client.fetch_history(
                    multi_address,
                    lambda ec, history, order=order: cb(ec, history, order)
                )

            reactor.callFromThread(get_history)
        except Exception as e:
            self.log.debug('Error: %s', e)
Ejemplo n.º 25
0
    def get_order(self, order_id, by_buyer_id=False):

        if not by_buyer_id:
            _order = self.db.selectEntries("orders", {"order_id": order_id})[0]
        else:
            _order = self.db.selectEntries("orders",
                                           {"buyer_order_id": order_id})[0]
        total_price = 0

        offer_data_json = self.get_offer_json(_order['signed_contract_body'],
                                              _order['state'])
        buyer_data_json = self.get_buyer_json(_order['signed_contract_body'],
                                              _order['state'])

        if _order['state'] != Orders.State.SENT:
            notary_json = self.get_notary_json(_order['signed_contract_body'],
                                               _order['state'])
            notary = notary_json['Notary']['notary_GUID']
        else:
            notary = ""

        if _order['state'] in (Orders.State.NEED_TO_PAY,
                               Orders.State.NOTARIZED,
                               Orders.State.WAITING_FOR_PAYMENT,
                               Orders.State.PAID, Orders.State.BUYER_PAID,
                               Orders.State.SHIPPED):

            def cb(total):
                if self.transport.handler is not None:
                    self.transport.handler.send_to_client(
                        None, {
                            "type": "order_payment_amount",
                            "value": total
                        })

            pubkeys = [
                offer_data_json['Seller']['seller_BTC_uncompressed_pubkey'],
                buyer_data_json['Buyer']['buyer_BTC_uncompressed_pubkey'],
                notary_json['Notary']['notary_BTC_uncompressed_pubkey']
            ]

            script = mk_multisig_script(pubkeys, 2, 3)
            payment_address = scriptaddr(script)

            trust.get_unspent(payment_address, cb)

            if 'shipping_price' in _order:
                shipping_price = _order[
                    'shipping_price'] if _order['shipping_price'] != '' else 0
            else:
                shipping_price = 0

            try:
                total_price = str((Decimal(shipping_price) + Decimal(_order['item_price']))) \
                    if 'item_price' in _order else _order['item_price']
            except Exception as e:
                self.log.error('Probably not a number %s', e)

        # Generate QR code
        qr = self.get_qr_code(offer_data_json['Contract']['item_title'],
                              _order['address'], total_price)
        merchant_bitmessage = offer_data_json.get('Seller',
                                                  '').get('seller_Bitmessage')
        buyer_bitmessage = buyer_data_json.get('Buyer',
                                               '').get('buyer_Bitmessage')

        # Get order prototype object before storing
        order = {
            "id": _order['id'],
            "state": _order.get('state'),
            "address": _order.get('address'),
            "buyer": _order.get('buyer'),
            "merchant": _order.get('merchant'),
            "order_id": _order.get('order_id'),
            "item_price": _order.get('item_price'),
            "shipping_price": _order.get('shipping_price'),
            "shipping_address": str(_order.get('shipping_address')),
            "total_price": total_price,
            "merchant_bitmessage": merchant_bitmessage,
            "buyer_bitmessage": buyer_bitmessage,
            "notary": notary,
            "payment_address": _order.get('payment_address'),
            "payment_address_amount": _order.get('payment_address_amount'),
            "qrcode": 'data:image/png;base64,' + qr,
            "item_title": offer_data_json['Contract']['item_title'],
            "signed_contract_body": _order.get('signed_contract_body'),
            "note_for_merchant": _order.get('note_for_merchant'),
            "updated": _order.get('updated')
        }

        if 'item_images' in offer_data_json['Contract'] and offer_data_json[
                'Contract']['item_images'] != {}:
            order['item_image'] = offer_data_json['Contract']['item_images']
        else:
            order['item_image'] = "img/no-photo.png"

        self.log.datadump('FULL ORDER: %s', order)

        return order
Ejemplo n.º 26
0
    def handle_bid_order(self, bid):

        self.log.info('Bid Order: %s', bid)

        new_peer = self.transport.get_crypto_peer(bid.get('merchantGUID'),
                                                  bid.get('merchantURI'),
                                                  bid.get('merchantPubkey'))

        # Generate unique id for this bid
        order_id = random.randint(0, 1000000)
        while len(self.db.selectEntries("contracts", {"id": order_id})) > 0:
            order_id = random.randint(0, 1000000)

        # Add to contract and sign
        contract = bid.get('rawContract')

        contract_stripped = "".join(contract.split('\n'))

        bidder_pgp_start_index = contract_stripped.find(
            "buyer_pgp", 0, len(contract_stripped))
        bidder_pgp_end_index = contract_stripped.find("buyer_GUID", 0,
                                                      len(contract_stripped))
        bidder_pgp = contract_stripped[bidder_pgp_start_index +
                                       13:bidder_pgp_end_index]

        self.gpg.import_keys(bidder_pgp)
        v = self.gpg.verify(contract)
        if v:
            self.log.info('Sellers contract verified')

        notary_section = {}

        notary_section['Notary'] = {
            'notary_GUID':
            self.transport.guid,
            'notary_BTC_uncompressed_pubkey':
            privkey_to_pubkey(self.transport.settings['privkey']),
            'notary_pgp':
            self.transport.settings['PGPPubKey'],
            'notary_fee':
            "",
            'notary_order_id':
            order_id
        }

        offer_data_json = self.get_offer_json(contract, Orders.State.SENT)
        bid_data_json = self.get_buyer_json(contract, Orders.State.SENT)

        pubkeys = [
            offer_data_json['Seller']['seller_BTC_uncompressed_pubkey'],
            bid_data_json['Buyer']['buyer_BTC_uncompressed_pubkey'],
            privkey_to_pubkey(self.transport.settings['privkey'])
        ]

        script = mk_multisig_script(pubkeys, 2, 3)
        multisig_address = scriptaddr(script)

        notary_section['Escrow'] = {
            'multisig_address': multisig_address,
            'redemption_script': script
        }

        self.log.debug('Notary: %s', notary_section)

        gpg = self.gpg

        # Prepare contract body
        notary_json = json.dumps(notary_section, indent=0)
        seg_len = 52

        out_text = "\n".join(notary_json[x:x + seg_len]
                             for x in range(0, len(notary_json), seg_len))

        # Append new data to contract
        out_text = "%s\n%s" % (contract, out_text)

        signed_data = gpg.sign(
            out_text,
            passphrase='P@ssw0rd',
            keyid=self.transport.settings.get('PGPPubkeyFingerprint'))

        self.log.debug('Double-signed Contract: %s', signed_data)

        # Hash the contract for storage
        contract_key = hashlib.sha1(str(signed_data)).hexdigest()
        hash_value = hashlib.new('ripemd160')
        hash_value.update(contract_key)
        contract_key = hash_value.hexdigest()

        self.log.info('Order ID: %s', order_id)

        # Push buy order to DHT and node if available
        # self.transport.store(contract_key, str(signed_data), self.transport.guid)
        # self.update_listings_index()

        # Find Seller Data in Contract
        offer_data = ''.join(contract.split('\n')[8:])
        index_of_seller_signature = offer_data.find(
            '- -----BEGIN PGP SIGNATURE-----', 0, len(offer_data))
        offer_data_json = "{\"Seller\": {" + offer_data[
            0:index_of_seller_signature]
        self.log.info('Offer Data: %s', offer_data_json)
        offer_data_json = json.loads(str(offer_data_json))

        # Find Buyer Data in Contract
        bid_data_index = offer_data.find('"Buyer"', index_of_seller_signature,
                                         len(offer_data))
        end_of_bid_index = offer_data.find('-----BEGIN PGP SIGNATURE',
                                           bid_data_index, len(offer_data))
        bid_data_json = "{" + offer_data[bid_data_index:end_of_bid_index]
        bid_data_json = json.loads(bid_data_json)
        self.log.info('Bid Data: %s', bid_data_json)

        buyer_order_id = "%s-%s" % (bid_data_json['Buyer']['buyer_GUID'],
                                    bid_data_json['Buyer']['buyer_order_id'])

        pubkeys = [
            offer_data_json['Seller']['seller_BTC_uncompressed_pubkey'],
            bid_data_json['Buyer']['buyer_BTC_uncompressed_pubkey'],
            privkey_to_pubkey(self.transport.settings['privkey'])
        ]

        script = mk_multisig_script(pubkeys, 2, 3)
        multisig_address = scriptaddr(script)

        self.db.insertEntry(
            "orders", {
                'market_id':
                self.transport.market_id,
                'contract_key':
                contract_key,
                'signed_contract_body':
                str(signed_data),
                'state':
                Orders.State.NOTARIZED,
                'buyer_order_id':
                buyer_order_id,
                'order_id':
                order_id,
                'merchant':
                offer_data_json['Seller']['seller_GUID'],
                'buyer':
                bid_data_json['Buyer']['buyer_GUID'],
                'address':
                multisig_address,
                'item_price':
                offer_data_json['Contract'].get('item_price', 0),
                'shipping_price':
                offer_data_json['Contract']['item_delivery'].get(
                    'shipping_price', ""),
                'note_for_merchant':
                bid_data_json['Buyer']['note_for_seller'],
                "updated":
                time.time()
            })

        # Send order to seller and buyer
        self.log.info('Sending notarized contract to buyer and seller %s', bid)

        if self.transport.handler is not None:
            self.transport.handler.send_to_client(
                None, {
                    "type": "order_notify",
                    "msg": "You just auto-notarized a contract."
                })

        notarized_order = {
            "type": "order",
            "state": "Notarized",
            "rawContract": str(signed_data)
        }

        if new_peer is not None:
            new_peer.send(notarized_order)
        self.transport.send(notarized_order,
                            bid_data_json['Buyer']['buyer_GUID'])

        self.log.info('Sent notarized contract to Seller and Buyer')
Ejemplo n.º 27
0
    def handle_notarized_order(self, msg):

        self.log.info('Handling notarized order')

        contract = msg['rawContract']

        # Find Seller Data in Contract
        offer_data = ''.join(contract.split('\n')[8:])
        index_of_seller_signature = offer_data.find(
            '- - -----BEGIN PGP SIGNATURE-----', 0, len(offer_data))
        offer_data_json = offer_data[0:index_of_seller_signature]
        self.log.info('Offer Data: %s', offer_data_json)
        offer_data_json = json.loads(str(offer_data_json))

        # Find Buyer Data in Contract
        bid_data_index = offer_data.find('"Buyer"', index_of_seller_signature,
                                         len(offer_data))
        end_of_bid_index = offer_data.find('- -----BEGIN PGP SIGNATURE',
                                           bid_data_index, len(offer_data))
        bid_data_json = "{" + offer_data[bid_data_index:end_of_bid_index]
        bid_data_json = json.loads(bid_data_json)
        self.log.info('Bid Data: %s', bid_data_json)

        # Find Notary Data in Contract
        notary_data_index = offer_data.find('"Notary"', end_of_bid_index,
                                            len(offer_data))
        end_of_notary_index = offer_data.find('-----BEGIN PGP SIGNATURE',
                                              notary_data_index,
                                              len(offer_data))
        notary_data_json = "{" + offer_data[
            notary_data_index:end_of_notary_index]
        notary_data_json = json.loads(notary_data_json)
        self.log.info('Notary Data: %s', notary_data_json)

        # Generate multi-sig address
        pubkeys = [
            offer_data_json['Seller']['seller_BTC_uncompressed_pubkey'],
            bid_data_json['Buyer']['buyer_BTC_uncompressed_pubkey'],
            notary_data_json['Notary']['notary_BTC_uncompressed_pubkey']
        ]
        script = mk_multisig_script(pubkeys, 2, 3)

        multisig_address = scriptaddr(script)

        seller_GUID = offer_data_json['Seller']['seller_GUID']

        order_id = bid_data_json['Buyer']['buyer_order_id']

        contract_key = hashlib.sha1(str(contract)).hexdigest()
        hash_value = hashlib.new('ripemd160')
        hash_value.update(contract_key)
        contract_key = hash_value.hexdigest()

        if seller_GUID == self.transport.guid:
            self.log.info('I am the seller!')
            state = 'Waiting for Payment'

            merchant_order_id = random.randint(0, 1000000)
            while len(self.db.selectEntries("orders", {"id": order_id})) > 0:
                merchant_order_id = random.randint(0, 1000000)

            buyer_id = "%s-%s" % (bid_data_json['Buyer']['buyer_GUID'],
                                  bid_data_json['Buyer']['buyer_order_id'])

            self.db.insertEntry(
                "orders", {
                    'market_id':
                    self.transport.market_id,
                    'contract_key':
                    contract_key,
                    'order_id':
                    merchant_order_id,
                    'signed_contract_body':
                    str(contract),
                    'state':
                    state,
                    'buyer_order_id':
                    buyer_id,
                    'merchant':
                    offer_data_json['Seller']['seller_GUID'],
                    'buyer':
                    bid_data_json['Buyer']['buyer_GUID'],
                    'notary':
                    notary_data_json['Notary']['notary_GUID'],
                    'address':
                    multisig_address,
                    'shipping_address':
                    self.transport.cryptor.decrypt(
                        bid_data_json['Buyer']['buyer_deliveryaddr'].decode(
                            'hex')),
                    'item_price':
                    offer_data_json['Contract'].get('item_price', 0),
                    'shipping_price':
                    offer_data_json['Contract']['item_delivery'].get(
                        'shipping_price', 0),
                    'note_for_merchant':
                    bid_data_json['Buyer']['note_for_seller'],
                    "updated":
                    time.time()
                })

            self.transport.handler.send_to_client(
                None, {
                    "type": "order_notify",
                    "msg": "You just received a new order."
                })

        else:
            self.log.info('I am the buyer')
            state = 'Need to Pay'

            self.db.updateEntries(
                "orders", {
                    'market_id':
                    self.transport.market_id,
                    'contract_key':
                    contract_key,
                    'signed_contract_body':
                    str(contract),
                    'state':
                    state,
                    'merchant':
                    offer_data_json['Seller']['seller_GUID'],
                    'buyer':
                    bid_data_json['Buyer']['buyer_GUID'],
                    'notary':
                    notary_data_json['Notary']['notary_GUID'],
                    'address':
                    multisig_address,
                    'shipping_address':
                    json.dumps(self.get_shipping_address()),
                    'item_price':
                    offer_data_json['Contract'].get('item_price', 0),
                    'shipping_price':
                    offer_data_json['Contract']['item_delivery'].get(
                        'shipping_price', ''),
                    'note_for_merchant':
                    bid_data_json['Buyer']['note_for_seller'],
                    "updated":
                    time.time()
                }, {'order_id': order_id})

            self.transport.handler.send_to_client(
                None, {
                    "type": "order_notify",
                    "msg": "Your order requires payment now."
                })