URI: 
       textend bitcoin: URI with signature data, instead of serialized format - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit e77f0c98e774f1566ec7f0cb78ac41f2d462c608
   DIR parent 1e668209dcbec5ccf32121e9199f3ff2bc671e81
  HTML Author: ThomasV <thomasv@gitorious>
       Date:   Tue, 21 Jul 2015 11:40:55 +0200
       
       extend bitcoin: URI with signature data, instead of serialized format
       
       Diffstat:
         M gui/qt/__init__.py                  |       4 ++--
         M gui/qt/main_window.py               |      78 ++++++++++++++-----------------
         M gui/qt/paytoedit.py                 |       2 +-
         M lib/paymentrequest.py               |       8 +++-----
         M lib/util.py                         |      11 +++++++++--
         M plugins/email.py                    |       5 ++++-
       
       6 files changed, 54 insertions(+), 54 deletions(-)
       ---
   DIR diff --git a/gui/qt/__init__.py b/gui/qt/__init__.py
       t@@ -57,7 +57,7 @@ class OpenFileEventFilter(QObject):
            def eventFilter(self, obj, event):
                if event.type() == QtCore.QEvent.FileOpen:
                    if len(self.windows) >= 1:
       -                self.windows[0].pay_from_URI(event.url().toEncoded())
       +                self.windows[0].pay_to_URI(event.url().toEncoded())
                        return True
                return False
        
       t@@ -140,7 +140,7 @@ class ElectrumGui:
                return int(qtVersion[0]) >= 4 and int(qtVersion[2]) >= 7
        
            def set_url(self, uri):
       -        self.current_window.pay_from_URI(uri)
       +        self.current_window.pay_to_URI(uri)
        
            def run_wizard(self, storage, action):
                import installwizard
   DIR diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -698,26 +698,29 @@ class ElectrumWindow(QMainWindow):
                self.update_receive_tab()
                self.clear_receive_tab()
        
       -    def get_receive_URI(self):
       -        addr = str(self.receive_address_e.text())
       -        amount = self.receive_amount_e.get_amount()
       -        message = unicode(self.receive_message_e.text())
       +    def get_request_URI(self, addr):
       +        req = self.wallet.receive_requests[addr]
       +        message = self.wallet.labels.get(addr, '')
       +        amount = req['amount']
                URI = util.create_URI(addr, amount, message)
       -        return URI
       +        if req.get('id') and req.get('sig'):
       +            sig = req.get('sig').decode('hex')
       +            sig = bitcoin.base_encode(sig, base=58)
       +            URI += "&id=" + req['id'] + "&sig="+sig 
       +            if req.get('timestamp'):
       +                URI += "&timestamp=%d"%req.get('timestamp')
       +            if req.get('expiration'):
       +                URI += "&expiration=%d"%req.get('expiration')
       +        return str(URI)
        
            def receive_list_menu(self, position):
                item = self.receive_list.itemAt(position)
                addr = str(item.text(2))
                req = self.wallet.receive_requests[addr]
       -        time, amount = req['timestamp'], req['amount']
       -        message = self.wallet.labels.get(addr, '')
       -        URI = util.create_URI(addr, amount, message)
                menu = QMenu()
       -        menu.addAction(_("Copy Address"), lambda: self.app.clipboard().setText(addr))
       -        menu.addAction(_("Copy URI"), lambda: self.app.clipboard().setText(str(URI)))
       -        if req.get('signature'):
       -            menu.addAction(_("Copy Signed URI"), lambda: self.view_signed_request(addr))
       -        menu.addAction(_("Save as BIP70 file"), lambda: self.export_payment_request(addr)) #.setEnabled(amount is not None)
       +        menu.addAction(_("Copy Address"), lambda: self.view_and_paste(_('Address'), '', addr))
       +        menu.addAction(_("Copy URI"), lambda: self.view_and_paste('URI', '', self.get_request_URI(addr)))
       +        menu.addAction(_("Save as BIP70 file"), lambda: self.export_payment_request(addr))
                menu.addAction(_("Delete"), lambda: self.delete_payment_request(item))
                run_hook('receive_list_menu', menu, addr)
                menu.exec_(self.receive_list.viewport().mapToGlobal(position))
       t@@ -745,8 +748,8 @@ class ElectrumWindow(QMainWindow):
                                return
                pr, requestor = paymentrequest.make_request(self.config, req, alias, alias_privkey)
                if requestor:
       -            req['requestor'] = requestor
       -            req['signature'] = pr.signature.encode('hex')
       +            req['id'] = requestor
       +            req['sig'] = pr.signature.encode('hex')
                self.wallet.add_payment_request(req, self.config)
        
            def save_payment_request(self):
       t@@ -765,29 +768,20 @@ class ElectrumWindow(QMainWindow):
                self.update_address_tab()
                self.save_request_button.setEnabled(False)
        
       -    def view_signed_request(self, addr):
       -        import urllib
       -        r = self.wallet.receive_requests.get(addr)
       -        pr = paymentrequest.serialize_request(r).SerializeToString()
       -        pr_text = 'bitcoin:?s=' + bitcoin.base_encode(pr, base=58)
       +    def view_and_paste(self, title, msg, data):
                dialog = QDialog(self)
       -        dialog.setWindowTitle(_("Signed Request"))
       +        dialog.setWindowTitle(title)
                vbox = QVBoxLayout()
       -        pr_e = ShowQRTextEdit(text=pr_text)
       -        pr_e.addCopyButton(self.app)
       -        msg = ' '.join([_('The following URI contains your payment request signed with your OpenAlias key.'),
       -                        _('The signature is a proof that the payment was requested by you.')])
       -        l = QLabel(msg)
       -        l.setWordWrap(True)
       -        vbox.addWidget(l)
       +        label = QLabel(msg)
       +        label.setWordWrap(True)
       +        vbox.addWidget(label)
       +        pr_e = ShowQRTextEdit(text=data)
                vbox.addWidget(pr_e)
       -        msg = _('Note: This format is experimental and may not be supported by other Bitcoin clients.')
       -        vbox.addWidget(QLabel(msg))
                vbox.addLayout(Buttons(CopyCloseButton(pr_e.text, self.app, dialog)))
                dialog.setLayout(vbox)
       +        #print len(data), data
                dialog.exec_()
        
       -
            def export_payment_request(self, addr):
                r = self.wallet.receive_requests.get(addr)
                pr = paymentrequest.serialize_request(r).SerializeToString()
       t@@ -883,8 +877,8 @@ class ElectrumWindow(QMainWindow):
                    message = req.get('memo', '')
                    date = format_time(timestamp)
                    status = req.get('status')
       -            signature = req.get('signature')
       -            requestor = req.get('requestor', '')
       +            signature = req.get('sig')
       +            requestor = req.get('id', '')
                    amount_str = self.format_amount(amount) if amount else ""
                    account = ''
                    item = QTreeWidgetItem([date, account, address, '', message, amount_str, pr_tooltips.get(status,'')])
       t@@ -1343,7 +1337,7 @@ class ElectrumWindow(QMainWindow):
                self.show_message(self.payment_request.error)
                self.payment_request = None
        
       -    def pay_from_URI(self,URI):
       +    def pay_to_URI(self, URI):
                if not URI:
                    return
                try:
       t@@ -1354,13 +1348,14 @@ class ElectrumWindow(QMainWindow):
                self.tabs.setCurrentIndex(1)
        
                r = out.get('r')
       -        s = out.get('s')
       -        if r or s:
       +        sig = out.get('sig')
       +        _id = out.get('id')
       +        if r or (_id and sig):
                    def get_payment_request_thread():
       -                if s:
       +                if _id and sig:
                            from electrum import paymentrequest
       -                    data = bitcoin.base_decode(s, None, base=58)
       -                    self.payment_request = paymentrequest.PaymentRequest(data)
       +                    pr = paymentrequest.serialize_request(out).SerializeToString()
       +                    self.payment_request = paymentrequest.PaymentRequest(pr)
                        else:
                            self.payment_request = get_payment_request(r)
                        if self.payment_request.verify(self.contacts):
       t@@ -1394,19 +1389,16 @@ class ElectrumWindow(QMainWindow):
                    self.amount_e.textEdited.emit("")
        
        
       -
            def do_clear(self):
                self.not_enough_funds = False
                self.payto_e.is_pr = False
                for e in [self.payto_e, self.message_e, self.amount_e, self.fee_e]:
                    e.setText('')
                    e.setFrozen(False)
       -
                self.set_pay_from([])
                self.update_status()
                run_hook('do_clear')
        
       -
            def set_frozen_state(self, addrs, freeze):
                self.wallet.set_frozen_state(addrs, freeze)
                self.update_address_tab()
       t@@ -2215,7 +2207,7 @@ class ElectrumWindow(QMainWindow):
                    return
                # if the user scanned a bitcoin URI
                if data.startswith("bitcoin:"):
       -            self.pay_from_URI(data)
       +            self.pay_to_URI(data)
                    return
                # else if the user scanned an offline signed tx
                # transactions are binary, but qrcode seems to return utf8...
   DIR diff --git a/gui/qt/paytoedit.py b/gui/qt/paytoedit.py
       t@@ -47,7 +47,7 @@ class PayToEdit(ScanQRTextEdit):
                self.errors = []
                self.is_pr = False
                self.is_alias = False
       -        self.scan_f = win.pay_from_URI
       +        self.scan_f = win.pay_to_URI
                self.update_size()
                self.payto_address = None
        
   DIR diff --git a/lib/paymentrequest.py b/lib/paymentrequest.py
       t@@ -318,7 +318,6 @@ def sign_request_with_alias(pr, alias, alias_privkey):
            address = bitcoin.address_from_private_key(alias_privkey)
            compressed = bitcoin.is_compressed(alias_privkey)
            pr.signature = ec_key.sign_message(message, compressed, address)
       -    return pr
        
        
        def sign_request_with_x509(pr, key_path, cert_path):
       t@@ -336,14 +335,13 @@ def sign_request_with_x509(pr, key_path, cert_path):
            hashBytes = bytearray(hashlib.sha256(msgBytes).digest())
            sig = rsakey.sign(x509.PREFIX_RSA_SHA256 + hashBytes)
            pr.signature = bytes(sig)
       -    return pr
        
        
        def serialize_request(req):
            pr = make_unsigned_request(req)
       -    signature = req.get('signature')
       -    if signature:
       -        requestor = req.get('requestor')
       +    signature = req.get('sig')
       +    requestor = req.get('id')
       +    if requestor and signature:
                pr.signature = signature.decode('hex')
                pr.pki_type = 'dnssec+btc'
                pr.pki_data = str(requestor)
   DIR diff --git a/lib/util.py b/lib/util.py
       t@@ -261,7 +261,7 @@ def parse_URI(uri):
            for k, v in pq.items():
                if len(v)!=1:
                    raise Exception('Duplicate Key', k)
       -        if k not in ['amount', 'label', 'message', 'r', 's']:
       +        if k not in ['amount', 'label', 'message', 'r', 'id', 'sig', 'timestamp', 'expiration']:
                    raise BaseException('Unknown key', k)
        
            out = {k: v[0] for k, v in pq.items()}
       t@@ -276,9 +276,16 @@ def parse_URI(uri):
                    amount = Decimal(m.group(1)) * pow(  Decimal(10) , k)
                else:
                    amount = Decimal(am) * COIN
       -        out['amount'] = amount
       +        out['amount'] = int(amount)
            if 'message' in out:
                out['message'] = out['message'].decode('utf8')
       +        out['memo'] = out['message']
       +    if 'timestamp' in out:
       +        out['timestamp'] = int(out['timestamp'])
       +        out['expiration'] = int(out['expiration'])
       +    if 'sig' in out:
       +        out['sig'] = bitcoin.base_decode(out['sig'], None, base=58).encode('hex')
       +
            return out
        
        
   DIR diff --git a/plugins/email.py b/plugins/email.py
       t@@ -148,7 +148,10 @@ class Plugin(BasePlugin):
                from electrum import paymentrequest
                r = self.wallet.receive_requests.get(addr)
                message = r.get('memo', '')
       -        pr, requestor = paymentrequest.make_request(self.config, r)
       +        if r.get('signature'):
       +            pr = paymentrequest.serialize_request(r)
       +        else:
       +            pr, requestor = paymentrequest.make_request(self.config, r)
                if not pr:
                    return
                recipient, ok = QtGui.QInputDialog.getText(self.win, 'Send request', 'Send request to:')