pywallet/tests/test_keys.py
2017-11-22 09:56:31 +02:00

246 lines
9.4 KiB
Python

import binascii
from unittest import TestCase
import base58
from multimerchant.network import BitcoinMainNet
from multimerchant.network import BitcoinTestNet
from multimerchant.network import DogecoinMainNet
from multimerchant.network import LitecoinMainNet
from multimerchant.wallet.keys import ChecksumException
from multimerchant.wallet.keys import IncompatibleNetworkException
from multimerchant.wallet.keys import KeyParseError # TODO test this
from multimerchant.wallet.keys import PrivateKey
from multimerchant.wallet.keys import PublicKey
from multimerchant.wallet.utils import ensure_bytes
from multimerchant.wallet.utils import long_or_int
class _TestPrivateKeyBase(TestCase):
@classmethod
def setUpClass(cls):
# This private key chosen from the bitcoin docs:
# https://en.bitcoin.it/wiki/Wallet_import_format
cls.expected_key = \
b"0c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d"
cls.key = PrivateKey(long_or_int(cls.expected_key, 16))
class _TestPublicKeyBase(TestCase):
@classmethod
def setUpClass(cls):
# This private key chosen from the bitcoin docs:
# https://en.bitcoin.it/wiki/Wallet_import_format
cls.expected_private_key = \
b"18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725"
cls.private_key = PrivateKey(
long_or_int(cls.expected_private_key, 16))
cls.public_key = PublicKey.from_hex_key(
"04"
"50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352"
"2cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6")
class TestPrivateKey(_TestPrivateKeyBase):
def test_raw_key_hex(self):
exp = self.key._private_key.privkey.secret_multiplier
self.assertEqual(PrivateKey(exp), self.key)
def test_raw_key_hex_bytes(self):
key = binascii.unhexlify(self.key.get_key())
self.assertEqual(PrivateKey.from_hex_key(key), self.key)
def test_from_master_password(self):
password = "correct horse battery staple"
expected_wif = "5KJvsngHeMpm884wtkJNzQGaCErckhHJBGFsvd3VyK5qMZXj3hS"
expected_pub_address = "1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T"
key = PrivateKey.from_master_password(password)
self.assertEqual(key.export_to_wif(), expected_wif)
self.assertEqual(
key.get_public_key().to_address(), expected_pub_address)
def test_invalid_exponent(self):
self.assertRaises(ValueError, PrivateKey, 'abcd')
class TestWIF(_TestPrivateKeyBase):
@classmethod
def setUpClass(cls):
super(TestWIF, cls).setUpClass()
cls.expected_wif = \
'5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ'
def test_export_to_wif(self):
self.assertEqual(
self.key.export_to_wif(),
self.expected_wif)
def test_import_wif(self):
key = PrivateKey.from_wif(self.expected_wif)
self.assertEqual(key, self.key)
def test_import_wif_invalid_network(self):
self.assertRaises(
IncompatibleNetworkException, PrivateKey.from_wif,
self.key.export_to_wif(), BitcoinTestNet)
def test_import_wif_network(self):
# Make a wif for bitcoin testnet:
testnet_key = PrivateKey(
self.key._private_key.privkey.secret_multiplier,
network=BitcoinTestNet)
testnet_wif = testnet_key.export_to_wif()
# We should be able to load it properly
key = PrivateKey.from_wif(testnet_wif, BitcoinTestNet)
self.assertEqual(testnet_key, key)
def test_bad_checksum(self):
wif = self.key.export_to_wif()
bad_checksum = base58.b58encode(binascii.unhexlify('FFFFFFFF'))
wif = wif[:-8] + bad_checksum
self.assertRaises(ChecksumException, PrivateKey.from_wif, wif)
class TestPublicKey(_TestPublicKeyBase):
def test_leading_zeros(self):
"""This zero-leading x coordinate generated by:
pvk = '18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725' # nopep8
from ecdsa import SECP256k1
from ecdsa.ecdsa import Public_key
from multimerchant.wallet.utils import long_to_hex
pubkey = Public_key(
SECP256k1.generator,
SECP256k1.generator * long(pvk, 16))
for i in range(1, 10000):
p = pubkey.point * i
x = p.x()
k = long_to_hex(x, 64)
if k.startswith('0'):
print(i)
print(long_to_hex(p.x(), 64))
print(long_to_hex(p.y(), 64))
break
"""
expected_key = ensure_bytes(
"04"
"02cbfd5410fd04973c096a4275bf75070955ebd689f316a6fbd449980ba7b756"
"c559764e5c367c03e002751aaf4ef8ec40fe97cda9b2d3f14fdd4cd244e8fcd2")
public_key = PublicKey.from_hex_key(expected_key)
self.assertEqual(public_key.get_key(), expected_key)
def test_address(self):
expected_address = "16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM"
actual_address = self.public_key.to_address()
self.assertEqual(expected_address, actual_address)
def test_private_to_public(self):
self.assertEqual(
self.private_key.get_public_key(),
self.public_key)
def test_unhexlified_key(self):
key_bytes = binascii.unhexlify(self.public_key.get_key())
self.assertEqual(
PublicKey.from_hex_key(key_bytes),
self.public_key)
def test_bad_key(self):
self.assertRaises(KeyParseError, PublicKey.from_hex_key, 'badkey')
def test_bad_network_key(self):
key = self.public_key.get_key()
# Change the network constant
key = b"00" + key[2:]
self.assertRaises(KeyParseError,
PublicKey.from_hex_key, key)
def test_compressed(self):
compressed_key = self.public_key.get_key(compressed=True)
self.assertEqual(len(compressed_key), 66)
self.assertEqual(
PublicKey.from_hex_key(compressed_key), self.public_key)
def test_point(self):
self.assertEqual(PublicKey.from_point(self.public_key.to_point()),
self.public_key)
def test_public_pair(self):
self.assertEqual(
PublicKey.from_public_pair(self.public_key.to_public_pair()),
self.public_key)
class TestVectors(TestCase):
"""Test vectors
from https://github.com/bitcoin/bitcoin/blob/master/src/test/key_tests.cpp
"""
def _test(self, network, secret, address, compressed):
key = PrivateKey.from_wif(secret, network=network)
self.assertEqual(key.compressed, compressed)
self.assertEqual(address, key.get_public_key().to_address())
def test_1(self):
secret = "5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj"
address = "1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ"
self._test(BitcoinMainNet, secret, address, False)
def test_2(self):
secret = "5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3"
address = "1F5y5E5FMc5YzdJtB9hLaUe43GDxEKXENJ"
self._test(BitcoinMainNet, secret, address, False)
def test_3(self):
secret = "Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw"
address = "1NoJrossxPBKfCHuJXT4HadJrXRE9Fxiqs"
self._test(BitcoinMainNet, secret, address, True)
def test_4(self):
secret = "L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g"
address = "1CRj2HyM1CXWzHAXLQtiGLyggNT9WQqsDs"
self._test(BitcoinMainNet, secret, address, True)
# https://github.com/dogecoin/dogecoin/blob/master-1.5/src/test/key_tests.cpp # nopep8
def test_dogecoin_1(self):
secret = "6JFPe8b4jbpup7petSB98M8tcaqXCigji8fGrC8bEbbDQxQkQ68"
address = "DSpgzjPyfQB6ZzeSbMWpaZiTTxGf2oBCs4"
self._test(DogecoinMainNet, secret, address, False)
def test_dogecoin_2(self):
secret = "6KLE6U3w8x3rM7nA1ZQxR4KnyEzeirPEt4YaXWdY4roF7Tt96rq"
address = "DR9VqfbWgEHZhNst34KQnABQXpPWXeLAJD"
self._test(DogecoinMainNet, secret, address, False)
def test_dogecoin_3(self):
secret = "QP8WvtVMV2iU6y7LE27ksRspp4MAJizPWYovx88W71g1nfSdAhkV"
address = "D8jZ6R8uuyQwiybupiVs3eDCedKdZ5bYV3"
self._test(DogecoinMainNet, secret, address, True)
def test_dogecoin_4(self):
secret = "QTuro8Pwx5yaonvJmU4jbBfwuEmTViyAGNeNyfnG82o7HWJmnrLj"
address = "DP7rGcDbpAvMb1dKup981zNt1heWUuVLP7"
self._test(DogecoinMainNet, secret, address, True)
# https://github.com/litecoin-project/litecoin/blob/master-0.8/src/test/key_tests.cpp # nopep8
def test_litecoin_1(self):
secret = "6uu5bsZLA2Lm6yCxgwxDxHyZmhYeqBMLQT83Fyq738YhYucQPQf"
address = "LWaFezDtucfCA4xcVEfs3R3xfgGWjSwcZr"
self._test(LitecoinMainNet, secret, address, False)
def test_litecoin_2(self):
secret = "6vZDRwYgTNidWzmKs9x8QzQGeWCqbdUtNRpEKZMaP67ZSn8XMjb"
address = "LXwHM6mRd432EzLJYwuKQMPhTzrgr7ur9K"
self._test(LitecoinMainNet, secret, address, False)
def test_litecoin_3(self):
secret = "T6UsJv9hYpvDfM5noKYkB3vfeHxhyegkeWJ4y7qKeQJuyXMK11XX"
address = "LZWK8h7C166niP6GmpUmiGrvn4oxPqQgFV"
self._test(LitecoinMainNet, secret, address, True)
def test_litecoin_4(self):
secret = "T9PBs5kq9QrkBPxeGNWKitMi4XuFVr25jaXTnuopLVZxCUAJbixA"
address = "Lgb6tdqmdW3n5E12johSuEAqRMt4kAr7yu"
self._test(LitecoinMainNet, secret, address, True)