tsupport for OP_RETURN - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 2efad717d8af578af321681275009d0bce5865ba DIR parent 508d8a798f7bf7605d3b220386e042e62882614d HTML Author: ThomasV <thomasv@gitorious> Date: Fri, 27 Jun 2014 17:08:20 +0200 support for OP_RETURN Diffstat: M gui/qt/main_window.py | 7 ++++++- M gui/qt/paytoedit.py | 22 +++++++++++----------- M lib/transaction.py | 13 +++++++------ M lib/wallet.py | 6 ++++-- 4 files changed, 28 insertions(+), 20 deletions(-) --- DIR diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py t@@ -987,7 +987,12 @@ class ElectrumWindow(QMainWindow): return for addr, x in outputs: - if addr is None or not bitcoin.is_address(addr): + if addr is None: + QMessageBox.warning(self, _('Error'), _('Bitcoin Address is None'), _('OK')) + return + if addr.startswith('OP_RETURN:'): + continue + if not bitcoin.is_address(addr): QMessageBox.warning(self, _('Error'), _('Invalid Bitcoin Address'), _('OK')) return if x is None: DIR diff --git a/gui/qt/paytoedit.py b/gui/qt/paytoedit.py t@@ -69,9 +69,14 @@ class PayToEdit(QRTextEdit): self.setStyleSheet("QWidget { background-color:#ffcccc;}") def parse_address_and_amount(self, line): - x, y = line.split(',') - address = self.parse_address(x) - amount = self.parse_amount(y) + m = re.match('^OP_RETURN\s+"(.+)"$', line.strip()) + if m: + address = 'OP_RETURN:' + m.group(1) + amount = 0 + else: + x, y = line.split(',') + address = self.parse_address(x) + amount = self.parse_amount(y) return address, amount t@@ -121,7 +126,7 @@ class PayToEdit(QRTextEdit): self.outputs = outputs self.payto_address = None - if total: + if outputs: self.amount_edit.setAmount(total) else: self.amount_edit.setText("") t@@ -202,11 +207,7 @@ class PayToEdit(QRTextEdit): e.ignore() return - isShortcut = (e.modifiers() and Qt.ControlModifier) and e.key() == Qt.Key_E - - if not self.c or not isShortcut: - QTextEdit.keyPressEvent(self, e) - + QTextEdit.keyPressEvent(self, e) ctrlOrShift = e.modifiers() and (Qt.ControlModifier or Qt.ShiftModifier) if self.c is None or (ctrlOrShift and e.text().isEmpty()): t@@ -216,7 +217,7 @@ class PayToEdit(QRTextEdit): hasModifier = (e.modifiers() != Qt.NoModifier) and not ctrlOrShift; completionPrefix = self.textUnderCursor() - if not isShortcut and (hasModifier or e.text().isEmpty() or completionPrefix.length() < 1 or eow.contains(e.text().right(1)) ): + if hasModifier or e.text().isEmpty() or completionPrefix.length() < 1 or eow.contains(e.text().right(1)): self.c.popup().hide() return t@@ -228,4 +229,3 @@ class PayToEdit(QRTextEdit): cr.setWidth(self.c.popup().sizeHintForColumn(0) + self.c.popup().verticalScrollBar().sizeHint().width()) self.c.complete(cr) - DIR diff --git a/lib/transaction.py b/lib/transaction.py t@@ -428,9 +428,10 @@ def get_address_from_output_script(bytes): +push_script = lambda x: op_push(len(x)/2) + x class Transaction: - + def __init__(self, raw): self.raw = raw self.deserialize() t@@ -505,16 +506,17 @@ class Transaction: @classmethod def pay_script(self, addr): + if addr.startswith('OP_RETURN:'): + h = addr[10:].encode('hex') + return '6a' + push_script(h) addrtype, hash_160 = bc_address_to_hash_160(addr) if addrtype == 0: script = '76a9' # op_dup, op_hash_160 - script += '14' # push 0x14 bytes - script += hash_160.encode('hex') + script += push_script(hash_160.encode('hex')) script += '88ac' # op_equalverify, op_checksig elif addrtype == 5: script = 'a9' # op_hash_160 - script += '14' # push 0x14 bytes - script += hash_160.encode('hex') + script += push_script(hash_160.encode('hex')) script += '87' # op_equal else: raise t@@ -524,7 +526,6 @@ class Transaction: @classmethod def serialize( klass, inputs, outputs, for_sig = None ): - push_script = lambda x: op_push(len(x)/2) + x s = int_to_hex(1,4) # version s += var_int( len(inputs) ) # number of inputs for i in range(len(inputs)): DIR diff --git a/lib/wallet.py b/lib/wallet.py t@@ -350,7 +350,7 @@ class Abstract_Wallet: raise Exception("Address not found", address) def getpubkeys(self, addr): - assert is_valid(addr) and self.is_mine(addr) + assert is_address(addr) and self.is_mine(addr) account, sequence = self.get_address_index(addr) a = self.accounts[account] return a.get_pubkeys( sequence ) t@@ -779,7 +779,9 @@ class Abstract_Wallet: def make_unsigned_transaction(self, outputs, fee=None, change_addr=None, domain=None, coins=None ): for address, x in outputs: - assert is_valid(address), "Address " + address + " is invalid!" + if address.startswith('OP_RETURN:'): + continue + assert is_address(address), "Address " + address + " is invalid!" amount = sum( map(lambda x:x[1], outputs) ) inputs, total, fee = self.choose_tx_inputs( amount, fee, len(outputs), domain, coins ) if not inputs: