Browse Source

define constants for tx output types

283
ThomasV 9 years ago
parent
commit
0d52911561
  1. 9
      gui/android.py
  2. 3
      gui/kivy/uix/screens.py
  3. 6
      gui/qt/main_window.py
  4. 6
      gui/qt/paytoedit.py
  5. 4
      gui/stdio.py
  6. 12
      gui/text.py
  7. 6
      lib/bitcoin.py
  8. 4
      lib/coinchooser.py
  9. 8
      lib/commands.py
  10. 23
      lib/transaction.py
  11. 8
      lib/wallet.py
  12. 4
      plugins/ledger/ledger.py
  13. 5
      plugins/trezor/plugin.py
  14. 2
      plugins/trustedcoin/trustedcoin.py

9
gui/android.py

@ -21,12 +21,12 @@
from __future__ import absolute_import from __future__ import absolute_import
import android import android
from decimal import Decimal
import datetime, re
from electrum import SimpleConfig, Wallet, WalletStorage, format_satoshis from electrum import SimpleConfig, Wallet, WalletStorage, format_satoshis
from electrum.bitcoin import is_address, COIN from electrum.bitcoin import is_address, COIN, TYPE_ADDRESS
from electrum import util from electrum import util
from decimal import Decimal
import datetime, re
def modal_dialog(title, msg = None): def modal_dialog(title, msg = None):
@ -442,9 +442,8 @@ def pay_to(recipient, amount, label):
droid.dialogCreateSpinnerProgress("Electrum", "signing transaction...") droid.dialogCreateSpinnerProgress("Electrum", "signing transaction...")
droid.dialogShow() droid.dialogShow()
try: try:
tx = wallet.mktx([('address', recipient, amount)], password, config) tx = wallet.mktx([(TYPE_ADDRESS, recipient, amount)], password, config)
except Exception as e: except Exception as e:
modal_dialog('error', e.message) modal_dialog('error', e.message)
droid.dialogDismiss() droid.dialogDismiss()

3
gui/kivy/uix/screens.py

@ -26,7 +26,6 @@ from context_menu import ContextMenu
from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED
class CScreen(Factory.Screen): class CScreen(Factory.Screen):
__events__ = ('on_activate', 'on_deactivate', 'on_enter', 'on_leave') __events__ = ('on_activate', 'on_deactivate', 'on_enter', 'on_leave')
@ -254,7 +253,7 @@ class SendScreen(CScreen):
except: except:
self.app.show_error(_('Invalid amount') + ':\n' + self.screen.amount) self.app.show_error(_('Invalid amount') + ':\n' + self.screen.amount)
return return
outputs = [('address', address, amount)] outputs = [(bitcoin.TYPE_ADDRESS, address, amount)]
message = unicode(self.screen.message) message = unicode(self.screen.message)
fee = None fee = None
self.app.protected(self.send_tx, (outputs, fee, message)) self.app.protected(self.send_tx, (outputs, fee, message))

6
gui/qt/main_window.py

@ -34,7 +34,7 @@ import PyQt4.QtCore as QtCore
import icons_rc import icons_rc
from electrum.bitcoin import COIN, is_valid from electrum.bitcoin import COIN, is_valid, TYPE_ADDRESS
from electrum.plugins import run_hook from electrum.plugins import run_hook
from electrum.i18n import _ from electrum.i18n import _
from electrum.util import block_explorer, block_explorer_info, block_explorer_URL from electrum.util import block_explorer, block_explorer_info, block_explorer_URL
@ -1076,7 +1076,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
fee = self.fee_e.get_amount() if freeze_fee else None fee = self.fee_e.get_amount() if freeze_fee else None
if not outputs: if not outputs:
addr = self.payto_e.payto_address if self.payto_e.payto_address else self.dummy_address addr = self.payto_e.payto_address if self.payto_e.payto_address else self.dummy_address
outputs = [('address', addr, amount)] outputs = [(TYPE_ADDRESS, addr, amount)]
try: try:
tx = self.wallet.make_unsigned_transaction(self.get_coins(), outputs, self.config, fee) tx = self.wallet.make_unsigned_transaction(self.get_coins(), outputs, self.config, fee)
self.not_enough_funds = False self.not_enough_funds = False
@ -1180,7 +1180,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
if addr is None: if addr is None:
self.show_error(_('Bitcoin Address is None')) self.show_error(_('Bitcoin Address is None'))
return return
if _type == 'address' and not bitcoin.is_address(addr): if _type == TYPE_ADDRESS and not bitcoin.is_address(addr):
self.show_error(_('Invalid Bitcoin Address')) self.show_error(_('Invalid Bitcoin Address'))
return return
if amount is None: if amount is None:

6
gui/qt/paytoedit.py

@ -77,11 +77,11 @@ class PayToEdit(ScanQRTextEdit):
if n: if n:
script = str(n.group(1)).decode('hex') script = str(n.group(1)).decode('hex')
amount = self.parse_amount(y) amount = self.parse_amount(y)
return 'script', script, amount return bitcoin.TYPE_SCRIPT, script, amount
else: else:
address = self.parse_address(x) address = self.parse_address(x)
amount = self.parse_amount(y) amount = self.parse_amount(y)
return 'address', address, amount return bitcoin.TYPE_ADDRESS, address, amount
def parse_amount(self, x): def parse_amount(self, x):
p = pow(10, self.amount_edit.decimal_point()) p = pow(10, self.amount_edit.decimal_point())
@ -149,7 +149,7 @@ class PayToEdit(ScanQRTextEdit):
amount = self.amount_edit.get_amount() amount = self.amount_edit.get_amount()
except: except:
amount = None amount = None
self.outputs = [('address', self.payto_address, amount)] self.outputs = [(bitcoin.TYPE_ADDRESS, self.payto_address, amount)]
return self.outputs[:] return self.outputs[:]

4
gui/stdio.py

@ -3,7 +3,7 @@ _ = lambda x:x
#from i18n import _ #from i18n import _
from electrum.wallet import WalletStorage, Wallet from electrum.wallet import WalletStorage, Wallet
from electrum.util import format_satoshis, set_verbosity, StoreDict from electrum.util import format_satoshis, set_verbosity, StoreDict
from electrum.bitcoin import is_valid, COIN from electrum.bitcoin import is_valid, COIN, TYPE_ADDRESS
from electrum.network import filter_protocol from electrum.network import filter_protocol
import sys, getpass, datetime import sys, getpass, datetime
@ -187,7 +187,7 @@ class ElectrumGui:
if c == "n": return if c == "n": return
try: try:
tx = self.wallet.mktx( [(self.str_recipient, amount)], password, self.config, fee) tx = self.wallet.mktx([(TYPE_ADDRESS, self.str_recipient, amount)], password, self.config, fee)
except Exception as e: except Exception as e:
print(str(e)) print(str(e))
return return

12
gui/text.py

@ -1,13 +1,14 @@
import tty, sys
import curses, datetime, locale import curses, datetime, locale
from decimal import Decimal from decimal import Decimal
_ = lambda x:x
from electrum.util import format_satoshis, set_verbosity from electrum.util import format_satoshis, set_verbosity
from electrum.util import StoreDict from electrum.util import StoreDict
from electrum.bitcoin import is_valid, COIN from electrum.bitcoin import is_valid, COIN, TYPE_ADDRESS
from electrum import Wallet, WalletStorage from electrum import Wallet, WalletStorage
import tty, sys _ = lambda x:x
class ElectrumGui: class ElectrumGui:
@ -327,9 +328,8 @@ class ElectrumGui:
return return
else: else:
password = None password = None
try: try:
tx = self.wallet.mktx( [(self.str_recipient, amount)], password, self.config, fee) tx = self.wallet.mktx([(TYPE_ADDRESS, self.str_recipient, amount)], password, self.config, fee)
except Exception as e: except Exception as e:
self.show_message(str(e)) self.show_message(str(e))
return return

6
lib/bitcoin.py

@ -34,6 +34,12 @@ RECOMMENDED_FEE = 50000
COINBASE_MATURITY = 100 COINBASE_MATURITY = 100
COIN = 100000000 COIN = 100000000
# supported types of transction outputs
TYPE_ADDRESS = 0
TYPE_PUBKEY = 1
TYPE_SCRIPT = 2
# AES encryption # AES encryption
EncodeAES = lambda secret, s: base64.b64encode(aes.encryptData(secret,s)) EncodeAES = lambda secret, s: base64.b64encode(aes.encryptData(secret,s))
DecodeAES = lambda secret, e: aes.decryptData(secret, base64.b64decode(e)) DecodeAES = lambda secret, e: aes.decryptData(secret, base64.b64decode(e))

4
lib/coinchooser.py

@ -20,7 +20,7 @@ from collections import defaultdict, namedtuple
from random import choice, randint, shuffle from random import choice, randint, shuffle
from math import floor, log10 from math import floor, log10
from bitcoin import COIN from bitcoin import COIN, TYPE_ADDRESS
from transaction import Transaction from transaction import Transaction
from util import NotEnoughFunds, PrintError, profiler from util import NotEnoughFunds, PrintError, profiler
@ -72,7 +72,7 @@ class CoinChooserBase(PrintError):
# size of the change output, add it to the transaction. # size of the change output, add it to the transaction.
dust = sum(amount for amount in amounts if amount < dust_threshold) dust = sum(amount for amount in amounts if amount < dust_threshold)
amounts = [amount for amount in amounts if amount >= dust_threshold] amounts = [amount for amount in amounts if amount >= dust_threshold]
change = [('address', addr, amount) change = [(TYPE_ADDRESS, addr, amount)
for addr, amount in zip(change_addrs, amounts)] for addr, amount in zip(change_addrs, amounts)]
self.print_error('change:', change) self.print_error('change:', change)
if dust: if dust:

8
lib/commands.py

@ -31,7 +31,7 @@ from decimal import Decimal
import util import util
from util import print_msg, format_satoshis, print_stderr from util import print_msg, format_satoshis, print_stderr
import bitcoin import bitcoin
from bitcoin import is_address, hash_160_to_bc_address, hash_160, COIN from bitcoin import is_address, hash_160_to_bc_address, hash_160, COIN, TYPE_ADDRESS
from transaction import Transaction from transaction import Transaction
import paymentrequest import paymentrequest
from paymentrequest import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED from paymentrequest import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED
@ -200,7 +200,7 @@ class Commands:
break break
else: else:
raise BaseException('Transaction output not in wallet', prevout_hash+":%d"%prevout_n) raise BaseException('Transaction output not in wallet', prevout_hash+":%d"%prevout_n)
outputs = map(lambda x: ('address', x[0], int(COIN*x[1])), outputs.items()) outputs = map(lambda x: (TYPE_ADDRESS, x[0], int(COIN*x[1])), outputs.items())
tx = Transaction.from_io(tx_inputs, outputs) tx = Transaction.from_io(tx_inputs, outputs)
if not unsigned: if not unsigned:
self.wallet.sign_transaction(tx, self._password) self.wallet.sign_transaction(tx, self._password)
@ -404,14 +404,14 @@ class Commands:
if fee is None: if fee is None:
for i in inputs: for i in inputs:
self.wallet.add_input_info(i) self.wallet.add_input_info(i)
output = ('address', address, amount) output = (TYPE_ADDRESS, address, amount)
dummy_tx = Transaction.from_io(inputs, [output]) dummy_tx = Transaction.from_io(inputs, [output])
fee_per_kb = self.wallet.fee_per_kb(self.config) fee_per_kb = self.wallet.fee_per_kb(self.config)
fee = dummy_tx.estimated_fee(fee_per_kb) fee = dummy_tx.estimated_fee(fee_per_kb)
amount -= fee amount -= fee
else: else:
amount = int(COIN*Decimal(amount)) amount = int(COIN*Decimal(amount))
final_outputs.append(('address', address, amount)) final_outputs.append((TYPE_ADDRESS, address, amount))
coins = self.wallet.get_spendable_coins(domain) coins = self.wallet.get_spendable_coins(domain)
tx = self.wallet.make_unsigned_transaction(coins, final_outputs, self.config, fee, change_addr) tx = self.wallet.make_unsigned_transaction(coins, final_outputs, self.config, fee, change_addr)

23
lib/transaction.py

@ -36,6 +36,7 @@ import random
NO_SIGNATURE = 'ff' NO_SIGNATURE = 'ff'
class SerializationError(Exception): class SerializationError(Exception):
""" Thrown when there's a problem deserializing or serializing """ """ Thrown when there's a problem deserializing or serializing """
@ -393,20 +394,20 @@ def get_address_from_output_script(bytes):
# 65 BYTES:... CHECKSIG # 65 BYTES:... CHECKSIG
match = [ opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG ] match = [ opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG ]
if match_decoded(decoded, match): if match_decoded(decoded, match):
return 'pubkey', decoded[0][1].encode('hex') return TYPE_PUBKEY, decoded[0][1].encode('hex')
# Pay-by-Bitcoin-address TxOuts look like: # Pay-by-Bitcoin-address TxOuts look like:
# DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG
match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ] match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ]
if match_decoded(decoded, match): if match_decoded(decoded, match):
return 'address', hash_160_to_bc_address(decoded[2][1]) return TYPE_ADDRESS, hash_160_to_bc_address(decoded[2][1])
# p2sh # p2sh
match = [ opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUAL ] match = [ opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUAL ]
if match_decoded(decoded, match): if match_decoded(decoded, match):
return 'address', hash_160_to_bc_address(decoded[1][1],5) return TYPE_ADDRESS, hash_160_to_bc_address(decoded[1][1],5)
return 'script', bytes return TYPE_SCRIPT, bytes
@ -542,7 +543,7 @@ class Transaction:
pubkey = public_key_from_private_key(privkey) pubkey = public_key_from_private_key(privkey)
address = address_from_private_key(privkey) address = address_from_private_key(privkey)
u = network.synchronous_get(('blockchain.address.listunspent',[address])) u = network.synchronous_get(('blockchain.address.listunspent',[address]))
pay_script = klass.pay_script('address', address) pay_script = klass.pay_script(TYPE_ADDRESS, address)
for item in u: for item in u:
item['scriptPubKey'] = pay_script item['scriptPubKey'] = pay_script
item['redeemPubkey'] = pubkey item['redeemPubkey'] = pubkey
@ -560,7 +561,7 @@ class Transaction:
return return
total = sum(i.get('value') for i in inputs) - fee total = sum(i.get('value') for i in inputs) - fee
outputs = [('address', to_address, total)] outputs = [(TYPE_ADDRESS, to_address, total)]
self = klass.from_io(inputs, outputs) self = klass.from_io(inputs, outputs)
self.sign(keypairs) self.sign(keypairs)
return self return self
@ -577,9 +578,9 @@ class Transaction:
@classmethod @classmethod
def pay_script(self, output_type, addr): def pay_script(self, output_type, addr):
if output_type == 'script': if output_type == TYPE_SCRIPT:
return addr.encode('hex') return addr.encode('hex')
elif output_type == 'address': elif output_type == TYPE_ADDRESS:
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
@ -636,7 +637,7 @@ class Transaction:
script += push_script(redeem_script) script += push_script(redeem_script)
elif for_sig==i: elif for_sig==i:
script = txin['redeemScript'] if p2sh else self.pay_script('address', address) script = txin['redeemScript'] if p2sh else self.pay_script(TYPE_ADDRESS, address)
else: else:
script = '' script = ''
@ -797,9 +798,9 @@ class Transaction:
"""convert pubkeys to addresses""" """convert pubkeys to addresses"""
o = [] o = []
for type, x, v in self.outputs: for type, x, v in self.outputs:
if type == 'address': if type == TYPE_ADDRESS:
addr = x addr = x
elif type == 'pubkey': elif type == TYPE_PUBKEY:
addr = public_key_to_bc_address(x.decode('hex')) addr = public_key_to_bc_address(x.decode('hex'))
else: else:
addr = 'SCRIPT ' + x.encode('hex') addr = 'SCRIPT ' + x.encode('hex')

8
lib/wallet.py

@ -658,7 +658,7 @@ class Abstract_Wallet(PrintError):
for i in inputs: for i in inputs:
self.add_input_info(i) self.add_input_info(i)
addr = self.addresses(False)[0] addr = self.addresses(False)[0]
output = ('address', addr, sendable) output = (TYPE_ADDRESS, addr, sendable)
dummy_tx = Transaction.from_io(inputs, [output]) dummy_tx = Transaction.from_io(inputs, [output])
if fee is None: if fee is None:
fee_per_kb = self.fee_per_kb(config) fee_per_kb = self.fee_per_kb(config)
@ -750,9 +750,9 @@ class Abstract_Wallet(PrintError):
for n, txo in enumerate(tx.outputs): for n, txo in enumerate(tx.outputs):
ser = tx_hash + ':%d'%n ser = tx_hash + ':%d'%n
_type, x, v = txo _type, x, v = txo
if _type == 'address': if _type == TYPE_ADDRESS:
addr = x addr = x
elif _type == 'pubkey': elif _type == TYPE_PUBKEY:
addr = public_key_to_bc_address(x.decode('hex')) addr = public_key_to_bc_address(x.decode('hex'))
else: else:
addr = None addr = None
@ -924,7 +924,7 @@ class Abstract_Wallet(PrintError):
def make_unsigned_transaction(self, coins, outputs, config, fixed_fee=None, change_addr=None): def make_unsigned_transaction(self, coins, outputs, config, fixed_fee=None, change_addr=None):
# check outputs # check outputs
for type, data, value in outputs: for type, data, value in outputs:
if type == 'address': if type == TYPE_ADDRESS:
assert is_address(data), "Address " + data + " is invalid!" assert is_address(data), "Address " + data + " is invalid!"
# Avoid index-out-of-range with coins[0] below # Avoid index-out-of-range with coins[0] below

4
plugins/ledger/ledger.py

@ -5,7 +5,7 @@ from sys import stderr
from time import sleep from time import sleep
import electrum import electrum
from electrum.bitcoin import EncodeBase58Check, DecodeBase58Check, public_key_to_bc_address, bc_address_to_hash_160 from electrum.bitcoin import EncodeBase58Check, DecodeBase58Check, public_key_to_bc_address, bc_address_to_hash_160, TYPE_ADDRESS
from electrum.i18n import _ from electrum.i18n import _
from electrum.plugins import BasePlugin, hook from electrum.plugins import BasePlugin, hook
from electrum.transaction import deserialize from electrum.transaction import deserialize
@ -203,7 +203,7 @@ class BTChipWallet(BIP44_Wallet):
if len(tx.outputs) > 2: # should never happen if len(tx.outputs) > 2: # should never happen
self.give_error("Transaction with more than 2 outputs not supported") self.give_error("Transaction with more than 2 outputs not supported")
for type, address, amount in tx.outputs: for type, address, amount in tx.outputs:
assert type == 'address' assert type == TYPE_ADDRESS
if self.is_change(address): if self.is_change(address):
changePath = self.address_id(address) changePath = self.address_id(address)
changeAmount = amount changeAmount = amount

5
plugins/trezor/plugin.py

@ -7,7 +7,8 @@ from struct import pack
from electrum.account import BIP32_Account from electrum.account import BIP32_Account
from electrum.bitcoin import (bc_address_to_hash_160, xpub_from_pubkey, from electrum.bitcoin import (bc_address_to_hash_160, xpub_from_pubkey,
public_key_to_bc_address, EncodeBase58Check) public_key_to_bc_address, EncodeBase58Check,
TYPE_ADDRESS)
from electrum.i18n import _ from electrum.i18n import _
from electrum.plugins import BasePlugin, hook from electrum.plugins import BasePlugin, hook
from electrum.transaction import (deserialize, is_extended_pubkey, from electrum.transaction import (deserialize, is_extended_pubkey,
@ -427,7 +428,7 @@ class TrezorCompatiblePlugin(BasePlugin, ThreadJob):
outputs = [] outputs = []
for type, address, amount in tx.outputs: for type, address, amount in tx.outputs:
assert type == 'address' assert type == TYPE_ADDRESS
txoutputtype = self.types.TxOutputType() txoutputtype = self.types.TxOutputType()
if wallet.is_change(address): if wallet.is_change(address):
address_path = wallet.address_id(address) address_path = wallet.address_id(address)

2
plugins/trustedcoin/trustedcoin.py

@ -234,7 +234,7 @@ class Wallet_2fa(Multisig_Wallet):
fee = self.extra_fee() fee = self.extra_fee()
if fee: if fee:
address = self.billing_info['billing_address'] address = self.billing_info['billing_address']
outputs = outputs + [('address', address, fee)] outputs = outputs + [(TYPE_ADDRESS, address, fee)]
try: try:
return BIP32_Wallet.make_unsigned_transaction( return BIP32_Wallet.make_unsigned_transaction(
self, coins, outputs, config, fixed_fee, change_addr) self, coins, outputs, config, fixed_fee, change_addr)

Loading…
Cancel
Save