support for OP_RETURN
This commit is contained in:
parent
508d8a798f
commit
2efad717d8
|
@ -987,7 +987,12 @@ class ElectrumWindow(QMainWindow):
|
||||||
return
|
return
|
||||||
|
|
||||||
for addr, x in outputs:
|
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'))
|
QMessageBox.warning(self, _('Error'), _('Invalid Bitcoin Address'), _('OK'))
|
||||||
return
|
return
|
||||||
if x is None:
|
if x is None:
|
||||||
|
|
|
@ -69,9 +69,14 @@ class PayToEdit(QRTextEdit):
|
||||||
self.setStyleSheet("QWidget { background-color:#ffcccc;}")
|
self.setStyleSheet("QWidget { background-color:#ffcccc;}")
|
||||||
|
|
||||||
def parse_address_and_amount(self, line):
|
def parse_address_and_amount(self, line):
|
||||||
x, y = line.split(',')
|
m = re.match('^OP_RETURN\s+"(.+)"$', line.strip())
|
||||||
address = self.parse_address(x)
|
if m:
|
||||||
amount = self.parse_amount(y)
|
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
|
return address, amount
|
||||||
|
|
||||||
|
|
||||||
|
@ -121,7 +126,7 @@ class PayToEdit(QRTextEdit):
|
||||||
self.outputs = outputs
|
self.outputs = outputs
|
||||||
self.payto_address = None
|
self.payto_address = None
|
||||||
|
|
||||||
if total:
|
if outputs:
|
||||||
self.amount_edit.setAmount(total)
|
self.amount_edit.setAmount(total)
|
||||||
else:
|
else:
|
||||||
self.amount_edit.setText("")
|
self.amount_edit.setText("")
|
||||||
|
@ -202,11 +207,7 @@ class PayToEdit(QRTextEdit):
|
||||||
e.ignore()
|
e.ignore()
|
||||||
return
|
return
|
||||||
|
|
||||||
isShortcut = (e.modifiers() and Qt.ControlModifier) and e.key() == Qt.Key_E
|
QTextEdit.keyPressEvent(self, e)
|
||||||
|
|
||||||
if not self.c or not isShortcut:
|
|
||||||
QTextEdit.keyPressEvent(self, e)
|
|
||||||
|
|
||||||
|
|
||||||
ctrlOrShift = e.modifiers() and (Qt.ControlModifier or Qt.ShiftModifier)
|
ctrlOrShift = e.modifiers() and (Qt.ControlModifier or Qt.ShiftModifier)
|
||||||
if self.c is None or (ctrlOrShift and e.text().isEmpty()):
|
if self.c is None or (ctrlOrShift and e.text().isEmpty()):
|
||||||
|
@ -216,7 +217,7 @@ class PayToEdit(QRTextEdit):
|
||||||
hasModifier = (e.modifiers() != Qt.NoModifier) and not ctrlOrShift;
|
hasModifier = (e.modifiers() != Qt.NoModifier) and not ctrlOrShift;
|
||||||
completionPrefix = self.textUnderCursor()
|
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()
|
self.c.popup().hide()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -228,4 +229,3 @@ class PayToEdit(QRTextEdit):
|
||||||
cr.setWidth(self.c.popup().sizeHintForColumn(0) + self.c.popup().verticalScrollBar().sizeHint().width())
|
cr.setWidth(self.c.popup().sizeHintForColumn(0) + self.c.popup().verticalScrollBar().sizeHint().width())
|
||||||
self.c.complete(cr)
|
self.c.complete(cr)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -428,9 +428,10 @@ def get_address_from_output_script(bytes):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
push_script = lambda x: op_push(len(x)/2) + x
|
||||||
|
|
||||||
class Transaction:
|
class Transaction:
|
||||||
|
|
||||||
def __init__(self, raw):
|
def __init__(self, raw):
|
||||||
self.raw = raw
|
self.raw = raw
|
||||||
self.deserialize()
|
self.deserialize()
|
||||||
|
@ -505,16 +506,17 @@ class Transaction:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def pay_script(self, addr):
|
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)
|
addrtype, hash_160 = bc_address_to_hash_160(addr)
|
||||||
if addrtype == 0:
|
if addrtype == 0:
|
||||||
script = '76a9' # op_dup, op_hash_160
|
script = '76a9' # op_dup, op_hash_160
|
||||||
script += '14' # push 0x14 bytes
|
script += push_script(hash_160.encode('hex'))
|
||||||
script += hash_160.encode('hex')
|
|
||||||
script += '88ac' # op_equalverify, op_checksig
|
script += '88ac' # op_equalverify, op_checksig
|
||||||
elif addrtype == 5:
|
elif addrtype == 5:
|
||||||
script = 'a9' # op_hash_160
|
script = 'a9' # op_hash_160
|
||||||
script += '14' # push 0x14 bytes
|
script += push_script(hash_160.encode('hex'))
|
||||||
script += hash_160.encode('hex')
|
|
||||||
script += '87' # op_equal
|
script += '87' # op_equal
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
@ -524,7 +526,6 @@ class Transaction:
|
||||||
@classmethod
|
@classmethod
|
||||||
def serialize( klass, inputs, outputs, for_sig = None ):
|
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 = int_to_hex(1,4) # version
|
||||||
s += var_int( len(inputs) ) # number of inputs
|
s += var_int( len(inputs) ) # number of inputs
|
||||||
for i in range(len(inputs)):
|
for i in range(len(inputs)):
|
||||||
|
|
|
@ -350,7 +350,7 @@ class Abstract_Wallet:
|
||||||
raise Exception("Address not found", address)
|
raise Exception("Address not found", address)
|
||||||
|
|
||||||
def getpubkeys(self, addr):
|
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)
|
account, sequence = self.get_address_index(addr)
|
||||||
a = self.accounts[account]
|
a = self.accounts[account]
|
||||||
return a.get_pubkeys( sequence )
|
return a.get_pubkeys( sequence )
|
||||||
|
@ -779,7 +779,9 @@ class Abstract_Wallet:
|
||||||
|
|
||||||
def make_unsigned_transaction(self, outputs, fee=None, change_addr=None, domain=None, coins=None ):
|
def make_unsigned_transaction(self, outputs, fee=None, change_addr=None, domain=None, coins=None ):
|
||||||
for address, x in outputs:
|
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) )
|
amount = sum( map(lambda x:x[1], outputs) )
|
||||||
inputs, total, fee = self.choose_tx_inputs( amount, fee, len(outputs), domain, coins )
|
inputs, total, fee = self.choose_tx_inputs( amount, fee, len(outputs), domain, coins )
|
||||||
if not inputs:
|
if not inputs:
|
||||||
|
|
Loading…
Reference in New Issue