ttest_bitcoin.py - electrum - Electrum Bitcoin wallet
HTML git clone https://git.parazyd.org/electrum
DIR Log
DIR Files
DIR Refs
DIR Submodules
---
ttest_bitcoin.py (53879B)
---
1 import base64
2 import sys
3
4 from electrum.bitcoin import (public_key_to_p2pkh, address_from_private_key,
5 is_address, is_private_key,
6 var_int, _op_push, address_to_script,
7 deserialize_privkey, serialize_privkey, is_segwit_address,
8 is_b58_address, address_to_scripthash, is_minikey,
9 is_compressed_privkey, EncodeBase58Check, DecodeBase58Check,
10 script_num_to_hex, push_script, add_number_to_script, int_to_hex,
11 opcodes, base_encode, base_decode, BitcoinException)
12 from electrum import bip32
13 from electrum.bip32 import (BIP32Node, convert_bip32_intpath_to_strpath,
14 xpub_from_xprv, xpub_type, is_xprv, is_bip32_derivation,
15 is_xpub, convert_bip32_path_to_list_of_uint32,
16 normalize_bip32_derivation, is_all_public_derivation)
17 from electrum.crypto import sha256d, SUPPORTED_PW_HASH_VERSIONS
18 from electrum import ecc, crypto, constants
19 from electrum.util import bfh, bh2u, InvalidPassword, randrange
20 from electrum.storage import WalletStorage
21 from electrum.keystore import xtype_from_derivation
22
23 from electrum import ecc_fast
24
25 from . import ElectrumTestCase
26 from . import TestCaseForTestnet
27 from . import FAST_TESTS
28
29
30 def needs_test_with_all_aes_implementations(func):
31 """Function decorator to run a unit test multiple times:
32 once with each AES implementation.
33
34 NOTE: this is inherently sequential;
35 tests running in parallel would break things
36 """
37 def run_test(*args, **kwargs):
38 if FAST_TESTS: # if set, only run tests once, using fastest implementation
39 func(*args, **kwargs)
40 return
41 has_cryptodome = crypto.HAS_CRYPTODOME
42 has_cryptography = crypto.HAS_CRYPTOGRAPHY
43 has_pyaes = crypto.HAS_PYAES
44 try:
45 if has_pyaes:
46 (crypto.HAS_CRYPTODOME, crypto.HAS_CRYPTOGRAPHY, crypto.HAS_PYAES) = False, False, True
47 func(*args, **kwargs) # pyaes
48 if has_cryptodome:
49 (crypto.HAS_CRYPTODOME, crypto.HAS_CRYPTOGRAPHY, crypto.HAS_PYAES) = True, False, False
50 func(*args, **kwargs) # cryptodome
51 if has_cryptography:
52 (crypto.HAS_CRYPTODOME, crypto.HAS_CRYPTOGRAPHY, crypto.HAS_PYAES) = False, True, False
53 func(*args, **kwargs) # cryptography
54 finally:
55 crypto.HAS_CRYPTODOME = has_cryptodome
56 crypto.HAS_CRYPTOGRAPHY = has_cryptography
57 crypto.HAS_PYAES = has_pyaes
58 return run_test
59
60
61 def needs_test_with_all_chacha20_implementations(func):
62 """Function decorator to run a unit test multiple times:
63 once with each ChaCha20/Poly1305 implementation.
64
65 NOTE: this is inherently sequential;
66 tests running in parallel would break things
67 """
68 def run_test(*args, **kwargs):
69 if FAST_TESTS: # if set, only run tests once, using fastest implementation
70 func(*args, **kwargs)
71 return
72 has_cryptodome = crypto.HAS_CRYPTODOME
73 has_cryptography = crypto.HAS_CRYPTOGRAPHY
74 try:
75 if has_cryptodome:
76 (crypto.HAS_CRYPTODOME, crypto.HAS_CRYPTOGRAPHY) = True, False
77 func(*args, **kwargs) # cryptodome
78 if has_cryptography:
79 (crypto.HAS_CRYPTODOME, crypto.HAS_CRYPTOGRAPHY) = False, True
80 func(*args, **kwargs) # cryptography
81 finally:
82 crypto.HAS_CRYPTODOME = has_cryptodome
83 crypto.HAS_CRYPTOGRAPHY = has_cryptography
84 return run_test
85
86
87 class Test_bitcoin(ElectrumTestCase):
88
89 def test_libsecp256k1_is_available(self):
90 # we want the unit testing framework to test with libsecp256k1 available.
91 self.assertTrue(bool(ecc_fast._libsecp256k1))
92
93 def test_pycryptodomex_is_available(self):
94 # we want the unit testing framework to test with pycryptodomex available.
95 self.assertTrue(bool(crypto.HAS_CRYPTODOME))
96
97 def test_cryptography_is_available(self):
98 # we want the unit testing framework to test with cryptography available.
99 self.assertTrue(bool(crypto.HAS_CRYPTOGRAPHY))
100
101 def test_pyaes_is_available(self):
102 # we want the unit testing framework to test with pyaes available.
103 self.assertTrue(bool(crypto.HAS_PYAES))
104
105 @needs_test_with_all_aes_implementations
106 def test_crypto(self):
107 for message in [b"Chancellor on brink of second bailout for banks", b'\xff'*512]:
108 self._do_test_crypto(message)
109
110 def _do_test_crypto(self, message):
111 G = ecc.GENERATOR
112 _r = G.order()
113 pvk = randrange(_r)
114
115 Pub = pvk*G
116 pubkey_c = Pub.get_public_key_bytes(True)
117 #pubkey_u = point_to_ser(Pub,False)
118 addr_c = public_key_to_p2pkh(pubkey_c)
119
120 #print "Private key ", '%064x'%pvk
121 eck = ecc.ECPrivkey.from_secret_scalar(pvk)
122
123 #print "Compressed public key ", pubkey_c.encode('hex')
124 enc = ecc.ECPubkey(pubkey_c).encrypt_message(message)
125 dec = eck.decrypt_message(enc)
126 self.assertEqual(message, dec)
127
128 #print "Uncompressed public key", pubkey_u.encode('hex')
129 #enc2 = EC_KEY.encrypt_message(message, pubkey_u)
130 dec2 = eck.decrypt_message(enc)
131 self.assertEqual(message, dec2)
132
133 signature = eck.sign_message(message, True)
134 #print signature
135 eck.verify_message_for_address(signature, message)
136
137 def test_ecc_sanity(self):
138 G = ecc.GENERATOR
139 n = G.order()
140 self.assertEqual(ecc.CURVE_ORDER, n)
141 inf = n * G
142 self.assertEqual(ecc.POINT_AT_INFINITY, inf)
143 self.assertTrue(inf.is_at_infinity())
144 self.assertFalse(G.is_at_infinity())
145 self.assertEqual(11 * G, 7 * G + 4 * G)
146 self.assertEqual((n + 2) * G, 2 * G)
147 self.assertEqual((n - 2) * G, -2 * G)
148 A = (n - 2) * G
149 B = (n - 1) * G
150 C = n * G
151 D = (n + 1) * G
152 self.assertFalse(A.is_at_infinity())
153 self.assertFalse(B.is_at_infinity())
154 self.assertTrue(C.is_at_infinity())
155 self.assertTrue((C * 5).is_at_infinity())
156 self.assertFalse(D.is_at_infinity())
157 self.assertEqual(inf, C)
158 self.assertEqual(inf, A + 2 * G)
159 self.assertEqual(inf, D + (-1) * G)
160 self.assertNotEqual(A, B)
161 self.assertEqual(2 * G, inf + 2 * G)
162 self.assertEqual(inf, 3 * G + (-3 * G))
163
164 def test_msg_signing(self):
165 msg1 = b'Chancellor on brink of second bailout for banks'
166 msg2 = b'Electrum'
167
168 def sign_message_with_wif_privkey(wif_privkey, msg):
169 txin_type, privkey, compressed = deserialize_privkey(wif_privkey)
170 key = ecc.ECPrivkey(privkey)
171 return key.sign_message(msg, compressed)
172
173 sig1 = sign_message_with_wif_privkey(
174 'L1TnU2zbNaAqMoVh65Cyvmcjzbrj41Gs9iTLcWbpJCMynXuap6UN', msg1)
175 addr1 = '15hETetDmcXm1mM4sEf7U2KXC9hDHFMSzz'
176 sig2 = sign_message_with_wif_privkey(
177 '5Hxn5C4SQuiV6e62A1MtZmbSeQyrLFhu5uYks62pU5VBUygK2KD', msg2)
178 addr2 = '1GPHVTY8UD9my6jyP4tb2TYJwUbDetyNC6'
179
180 sig1_b64 = base64.b64encode(sig1)
181 sig2_b64 = base64.b64encode(sig2)
182
183 self.assertEqual(sig1_b64, b'Hzsu0U/THAsPz/MSuXGBKSULz2dTfmrg1NsAhFp+wH5aKfmX4Db7ExLGa7FGn0m6Mf43KsbEOWpvUUUBTM3Uusw=')
184 self.assertEqual(sig2_b64, b'HBQdYfv7kOrxmRewLJnG7sV6KlU71O04hUnE4tai97p7Pg+D+yKaWXsdGgHTrKw90caQMo/D6b//qX50ge9P9iI=')
185
186 self.assertTrue(ecc.verify_message_with_address(addr1, sig1, msg1))
187 self.assertTrue(ecc.verify_message_with_address(addr2, sig2, msg2))
188
189 self.assertFalse(ecc.verify_message_with_address(addr1, b'wrong', msg1))
190 self.assertFalse(ecc.verify_message_with_address(addr1, sig2, msg1))
191
192 @needs_test_with_all_aes_implementations
193 def test_decrypt_message(self):
194 key = WalletStorage.get_eckey_from_password('pw123')
195 self.assertEqual(b'me<(s_s)>age', key.decrypt_message(b'QklFMQMDFtgT3zWSQsa+Uie8H/WvfUjlu9UN9OJtTt3KlgKeSTi6SQfuhcg1uIz9hp3WIUOFGTLr4RNQBdjPNqzXwhkcPi2Xsbiw6UCNJncVPJ6QBg=='))
196 self.assertEqual(b'me<(s_s)>age', key.decrypt_message(b'QklFMQKXOXbylOQTSMGfo4MFRwivAxeEEkewWQrpdYTzjPhqjHcGBJwdIhB7DyRfRQihuXx1y0ZLLv7XxLzrILzkl/H4YUtZB4uWjuOAcmxQH4i/Og=='))
parazyd.org:70 /git/electrum/file/electrum/tests/test_bitcoin.py.gph:206: line too long