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
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
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
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
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
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')
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
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 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']
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')
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']
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)
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)
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
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)
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)
def main(): scriptpubkey = getScriptPubKey(args.solution) addrP2SH = scriptaddr(scriptpubkey, ADDRESS_PREFIX) print('> P2SH Address: %s' % addrP2SH)
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."})
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')
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
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)
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
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')
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." })