electrum

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

commit f14d055ad83eaf39c692702a708bbcc5e0652935
parent 3a894725ae19583afa378ce6769120415826f5fe
Author: ThomasV <thomasv@gitorious>
Date:   Sat,  5 Oct 2013 21:15:48 +0200

choose_tx_from account, and use deterministic signatures (issue #323)

Diffstat:
Mgui/qt/main_window.py | 6+++---
Mlib/bitcoin.py | 25+++++++++++++------------
Mlib/commands.py | 2+-
Mlib/transaction.py | 2+-
Mlib/wallet.py | 13+++++--------
5 files changed, 23 insertions(+), 25 deletions(-)

diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py @@ -794,7 +794,7 @@ class ElectrumWindow(QMainWindow): if self.amount_e.is_shortcut: self.amount_e.is_shortcut = False c, u = self.wallet.get_account_balance(self.current_account) - inputs, total, fee = self.wallet.choose_tx_inputs( c + u, 0, self.current_account) + inputs, total, fee = self.wallet.choose_tx_inputs_from_account( c + u, 0, self.current_account) fee = self.wallet.estimated_fee(inputs) amount = c + u - fee self.amount_e.setText( self.format_amount(amount) ) @@ -807,7 +807,7 @@ class ElectrumWindow(QMainWindow): if not is_fee: fee = None if amount is None: return - inputs, total, fee = self.wallet.choose_tx_inputs( amount, fee, self.current_account ) + inputs, total, fee = self.wallet.choose_tx_inputs_from_account( amount, fee, self.current_account ) if not is_fee: self.fee_e.setText( self.format_amount( fee ) ) if inputs: @@ -1676,7 +1676,7 @@ class ElectrumWindow(QMainWindow): def do_verify(): message = unicode(verify_message.toPlainText()) message = message.encode('utf-8') - if self.wallet.verify_message(verify_address.text(), str(verify_signature.toPlainText()), message): + if bitcoin.verify_message(verify_address.text(), str(verify_signature.toPlainText()), message): self.show_message(_("Signature verified")) else: self.show_message(_("Error: wrong signature")) diff --git a/lib/bitcoin.py b/lib/bitcoin.py @@ -272,18 +272,9 @@ def is_valid(addr): ########### end pywallet functions ####################### -# secp256k1, http://www.oid-info.com/get/1.3.132.0.10 -_p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2FL -_r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141L -_b = 0x0000000000000000000000000000000000000000000000000000000000000007L -_a = 0x0000000000000000000000000000000000000000000000000000000000000000L -_Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798L -_Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8L -curve_secp256k1 = ecdsa.ellipticcurve.CurveFp( _p, _a, _b ) -generator_secp256k1 = ecdsa.ellipticcurve.Point( curve_secp256k1, _Gx, _Gy, _r ) -oid_secp256k1 = (1,3,132,0,10) -SECP256k1 = ecdsa.curves.Curve("SECP256k1", curve_secp256k1, generator_secp256k1, oid_secp256k1 ) +from ecdsa.ecdsa import curve_secp256k1, generator_secp256k1 +from ecdsa.curves import SECP256k1 from ecdsa.util import string_to_number, number_to_string def msg_magic(message): @@ -293,6 +284,16 @@ def msg_magic(message): return "\x18Bitcoin Signed Message:\n" + encoded_varint + message +def verify_message(address, signature, message): + try: + EC_KEY.verify_message(address, signature, message) + return True + except BaseException as e: + print_error("Verification error: {0}".format(e)) + return False + + + class EC_KEY(object): def __init__( self, secret ): self.pubkey = ecdsa.ecdsa.Public_key( generator_secp256k1, generator_secp256k1 * secret ) @@ -302,7 +303,7 @@ class EC_KEY(object): def sign_message(self, message, compressed, address): private_key = ecdsa.SigningKey.from_secret_exponent( self.secret, curve = SECP256k1 ) public_key = private_key.get_verifying_key() - signature = private_key.sign_digest( Hash( msg_magic(message) ), sigencode = ecdsa.util.sigencode_string ) + signature = private_key.sign_digest_deterministic( Hash( msg_magic(message) ), hashfunc=hashlib.sha256, sigencode = ecdsa.util.sigencode_string ) assert public_key.verify_digest( signature, Hash( msg_magic(message) ), sigdecode = ecdsa.util.sigdecode_string) for i in range(4): sig = base64.b64encode( chr(27 + i + (4 if compressed else 0)) + signature ) diff --git a/lib/commands.py b/lib/commands.py @@ -233,7 +233,7 @@ class Commands: def verifymessage(self, address, signature, message): - return self.wallet.verify_message(address, signature, message) + return bitcoin.verify_message(address, signature, message) def _mktx(self, outputs, fee = None, change_addr = None, domain = None): diff --git a/lib/transaction.py b/lib/transaction.py @@ -524,7 +524,7 @@ class Transaction: secexp = pkey.secret private_key = ecdsa.SigningKey.from_secret_exponent( secexp, curve = SECP256k1 ) public_key = private_key.get_verifying_key() - sig = private_key.sign_digest( Hash( tx_for_sig.decode('hex') ), sigencode = ecdsa.util.sigencode_der ) + sig = private_key.sign_digest_deterministic( Hash( tx_for_sig.decode('hex') ), hashfunc=hashlib.sha256, sigencode = ecdsa.util.sigencode_der ) assert public_key.verify_digest( sig, Hash( tx_for_sig.decode('hex') ), sigdecode = ecdsa.util.sigdecode_der) signatures.append( sig.encode('hex') ) print_error("adding signature for", pubkey) diff --git a/lib/wallet.py b/lib/wallet.py @@ -673,14 +673,6 @@ class Wallet: compressed = is_compressed(sec) return key.sign_message(message, compressed, address) - def verify_message(self, address, signature, message): - try: - EC_KEY.verify_message(address, signature, message) - return True - except BaseException as e: - print_error("Verification error: {0}".format(e)) - return False - def change_gap_limit(self, value): if value >= self.gap_limit: @@ -1005,6 +997,11 @@ class Wallet: + def choose_tx_inputs_from_account( self, amount, fixed_fee, account ): + domain = self.get_account_addresses(account) if account else None + return self.choose_tx_inputs( amount, fixed_fee, domain ) + + def choose_tx_inputs( self, amount, fixed_fee, domain = None ): """ todo: minimize tx size """ total = 0