electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 1bb00ff5af3a7f23f23c92b69cc2ff412731a7f3
parent 38e662e5227ae0fa819e353b65aa1195bb92ba9f
Author: ThomasV <thomasv@gitorious>
Date:   Tue,  8 Jul 2014 19:38:16 +0200

store output type explicitly in tuple

Diffstat:
Mgui/qt/main_window.py | 16++++++++--------
Mgui/qt/paytoedit.py | 12+++++++-----
Mgui/qt/transaction_dialog.py | 2+-
Mlib/commands.py | 3+--
Mlib/transaction.py | 39+++++++++++++++++++++------------------
Mlib/wallet.py | 13+++++++------
6 files changed, 45 insertions(+), 40 deletions(-)

diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py @@ -991,20 +991,20 @@ class ElectrumWindow(QMainWindow): QMessageBox.warning(self, _('Error'), _('No outputs'), _('OK')) return - for addr, x in outputs: + for type, addr, amount in outputs: if addr is None: QMessageBox.warning(self, _('Error'), _('Bitcoin Address is None'), _('OK')) return - if addr.startswith('OP_RETURN:'): + if type == 'op_return': continue - if not bitcoin.is_address(addr): + if type == 'address' and not bitcoin.is_address(addr): QMessageBox.warning(self, _('Error'), _('Invalid Bitcoin Address'), _('OK')) return - if x is None: + if amount is None: QMessageBox.warning(self, _('Error'), _('Invalid Amount'), _('OK')) return - amount = sum(map(lambda x:x[1], outputs)) + amount = sum(map(lambda x:x[2], outputs)) fee = self.fee_e.get_amount() if fee is None: @@ -1013,7 +1013,7 @@ class ElectrumWindow(QMainWindow): confirm_amount = self.config.get('confirm_amount', 100000000) if amount >= confirm_amount: - o = '\n'.join(map(lambda x:x[0], outputs)) + o = '\n'.join(map(lambda x:x[1], outputs)) if not self.question(_("send %(amount)s to %(address)s?")%{ 'amount' : self.format_amount(amount) + ' '+ self.base_unit(), 'address' : o}): return @@ -2136,12 +2136,12 @@ class ElectrumWindow(QMainWindow): try: for position, row in enumerate(csvReader): address = row[0] - if not is_valid(address): + if not is_address(address): errors.append((position, address)) continue amount = Decimal(row[1]) amount = int(100000000*amount) - outputs.append((address, amount)) + outputs.append(('address', address, amount)) except (ValueError, IOError, os.error), reason: QMessageBox.critical(None, _("Unable to read file or no transaction found"), _("Electrum was unable to open your transaction file") + "\n" + str(reason)) return diff --git a/gui/qt/paytoedit.py b/gui/qt/paytoedit.py @@ -69,13 +69,15 @@ class PayToEdit(QRTextEdit): def parse_address_and_amount(self, line): m = re.match('^OP_RETURN\s+"(.+)"$', line.strip()) if m: - address = 'OP_RETURN:' + m.group(1) + type = 'op_return' + address = m.group(1) amount = 0 else: x, y = line.split(',') + type = 'address' address = self.parse_address(x) amount = self.parse_amount(y) - return address, amount + return type, address, amount def parse_amount(self, x): @@ -114,11 +116,11 @@ class PayToEdit(QRTextEdit): for line in lines: try: - to_address, amount = self.parse_address_and_amount(line) + type, to_address, amount = self.parse_address_and_amount(line) except: continue - outputs.append((to_address, amount)) + outputs.append((type, to_address, amount)) total += amount self.outputs = outputs @@ -144,7 +146,7 @@ class PayToEdit(QRTextEdit): except: amount = None - self.outputs = [(self.payto_address, amount)] + self.outputs = [('address', self.payto_address, amount)] return self.outputs[:] diff --git a/gui/qt/transaction_dialog.py b/gui/qt/transaction_dialog.py @@ -212,7 +212,7 @@ class TxDialog(QDialog): vbox.addWidget(i_text) vbox.addWidget(QLabel(_("Outputs"))) - lines = map(lambda x: x[0] + u'\t\t' + self.parent.format_amount(x[1]), self.tx.outputs) + lines = map(lambda x: x[0] + u'\t\t' + self.parent.format_amount(x[1]), self.tx.get_outputs()) o_text = QTextEdit() o_text.setText('\n'.join(lines)) o_text.setReadOnly(True) diff --git a/lib/commands.py b/lib/commands.py @@ -268,7 +268,6 @@ class Commands: return bitcoin.verify_message(address, signature, message) def _mktx(self, outputs, fee = None, change_addr = None, domain = None): - for to_address, amount in outputs: if not is_valid(to_address): raise Exception("Invalid Bitcoin address", to_address) @@ -298,7 +297,7 @@ class Commands: break amount = int(100000000*amount) - final_outputs.append((to_address, amount)) + final_outputs.append(('address', to_address, amount)) if fee: fee = int(100000000*fee) return self.wallet.mktx(final_outputs, self.password, fee , change_addr, domain) diff --git a/lib/transaction.py b/lib/transaction.py @@ -416,20 +416,20 @@ def get_address_from_output_script(bytes): # 65 BYTES:... CHECKSIG match = [ opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG ] if match_decoded(decoded, match): - return "pubkey:" + decoded[0][1].encode('hex') + return 'pubkey', decoded[0][1].encode('hex') # Pay-by-Bitcoin-address TxOuts look like: # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ] if match_decoded(decoded, match): - return hash_160_to_bc_address(decoded[2][1]) + return 'address', hash_160_to_bc_address(decoded[2][1]) # p2sh match = [ opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUAL ] if match_decoded(decoded, match): - return hash_160_to_bc_address(decoded[1][1],5) + return 'address', hash_160_to_bc_address(decoded[1][1],5) - return "(None)" + return "(None)", "(None)" @@ -460,7 +460,8 @@ def parse_output(vds, i): d = {} d['value'] = vds.read_int64() scriptPubKey = vds.read_bytes(vds.read_compact_size()) - address = get_address_from_output_script(scriptPubKey) + type, address = get_address_from_output_script(scriptPubKey) + d['type'] = type d['address'] = address d['scriptPubKey'] = scriptPubKey.encode('hex') d['prevout_n'] = i @@ -510,7 +511,7 @@ class Transaction: d = deserialize(raw) self.raw = raw self.inputs = d['inputs'] - self.outputs = map(lambda x: (x['address'], x['value']), d['outputs']) + self.outputs = map(lambda x: (x['type'], x['address'], x['value']), d['outputs']) self.locktime = d['lockTime'] @@ -534,7 +535,7 @@ class Transaction: return total = sum( map(lambda x:int(x.get('value')), inputs) ) - fee - outputs = [(to_address, total)] + outputs = [('address', to_address, total)] self = klass(inputs, outputs) self.sign({ pubkey:privkey }) return self @@ -568,10 +569,12 @@ class Transaction: @classmethod - def pay_script(self, addr): - if addr.startswith('OP_RETURN:'): - h = addr[10:].encode('hex') + def pay_script(self, type, addr): + if type == 'op_return': + h = addr.encode('hex') return '6a' + push_script(h) + else: + assert type == 'address' addrtype, hash_160 = bc_address_to_hash_160(addr) if addrtype == 0: script = '76a9' # op_dup, op_hash_160 @@ -629,7 +632,7 @@ class Transaction: script += push_script(redeem_script) elif for_sig==i: - script = txin['redeemScript'] if p2sh else klass.pay_script(address) + script = txin['redeemScript'] if p2sh else klass.pay_script('address', address) else: script = '' s += var_int( len(script)/2 ) # script length @@ -638,9 +641,9 @@ class Transaction: s += var_int( len(outputs) ) # number of outputs for output in outputs: - addr, amount = output + type, addr, amount = output s += int_to_hex( amount, 8) # amount - script = klass.pay_script(addr) + script = klass.pay_script(type, addr) s += var_int( len(script)/2 ) # script length s += script # script s += int_to_hex(0,4) # lock time @@ -755,11 +758,11 @@ class Transaction: def get_outputs(self): """convert pubkeys to addresses""" o = [] - for x, v in self.outputs: - if bitcoin.is_address(x): + for type, x, v in self.outputs: + if type == 'address': addr = x - elif x.startswith('pubkey:'): - addr = public_key_to_bc_address(x[7:].decode('hex')) + elif type == 'pubkey': + addr = public_key_to_bc_address(x.decode('hex')) else: addr = "(None)" o.append((addr,v)) @@ -850,7 +853,7 @@ class Transaction: if size >= 10000: return True - for o in self.outputs: + for o in self.get_outputs(): value = o[1] if value < 1000000: return True diff --git a/lib/wallet.py b/lib/wallet.py @@ -207,8 +207,8 @@ class Abstract_Wallet: tx.add_pubkey_addresses(self.transactions) # outputs of tx: inputs of tx2 - for x, v in tx.outputs: - if x.startswith('pubkey:'): + for type, x, v in tx.outputs: + if type == 'pubkey': for tx2 in self.transactions.values(): tx2.add_pubkey_addresses({h:tx}) @@ -772,11 +772,12 @@ class Abstract_Wallet: return default_label def make_unsigned_transaction(self, outputs, fee=None, change_addr=None, domain=None, coins=None ): - for address, x in outputs: - if address.startswith('OP_RETURN:'): + for type, address, x in outputs: + if type == 'op_return': continue - assert is_address(address), "Address " + address + " is invalid!" - amount = sum( map(lambda x:x[1], outputs) ) + if type == 'address': + assert is_address(address), "Address " + address + " is invalid!" + amount = sum( map(lambda x:x[2], outputs) ) inputs, total, fee = self.choose_tx_inputs( amount, fee, len(outputs), domain, coins ) if not inputs: raise ValueError("Not enough funds")