version 0.2.0, new lib for bitcoin ecc, dont display or track notify errors, dont reload again within 1 sec, null peer ip fix, signingmoved to ContentManager, content.json include support, content.json multisig ready, content.json proper bitcoincore compatible signing, content.json include permissions, multithreaded publish, publish timeout 60s, no exception on invalid bitcoin address, testcase for new lib, bip32 based persite privatekey generation, multiuser ready, simple json database query command, websocket api fileGet, wrapper loading title stuck bugfix
2015-02-09 02:09:02 +01:00
|
|
|
import json
|
|
|
|
import os
|
|
|
|
import random
|
|
|
|
import unittest
|
|
|
|
|
|
|
|
import bitcoin.ripemd as ripemd
|
|
|
|
from bitcoin import *
|
|
|
|
|
|
|
|
|
|
|
|
class TestECCArithmetic(unittest.TestCase):
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
print('Starting ECC arithmetic tests')
|
|
|
|
|
|
|
|
def test_all(self):
|
|
|
|
for i in range(8):
|
|
|
|
print('### Round %d' % (i+1))
|
|
|
|
x, y = random.randrange(2**256), random.randrange(2**256)
|
|
|
|
self.assertEqual(
|
|
|
|
multiply(multiply(G, x), y)[0],
|
|
|
|
multiply(multiply(G, y), x)[0]
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
|
|
|
|
add_pubkeys(multiply(G, x), multiply(G, y))[0],
|
|
|
|
multiply(G, add_privkeys(x, y))[0]
|
|
|
|
)
|
|
|
|
|
|
|
|
hx, hy = encode(x % N, 16, 64), encode(y % N, 16, 64)
|
|
|
|
self.assertEqual(
|
|
|
|
multiply(multiply(G, hx), hy)[0],
|
|
|
|
multiply(multiply(G, hy), hx)[0]
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
add_pubkeys(multiply(G, hx), multiply(G, hy))[0],
|
|
|
|
multiply(G, add_privkeys(hx, hy))[0]
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
b58check_to_hex(pubtoaddr(privtopub(x))),
|
|
|
|
b58check_to_hex(pubtoaddr(multiply(G, hx), 23))
|
|
|
|
)
|
|
|
|
|
|
|
|
p = privtopub(sha256(str(x)))
|
|
|
|
if i % 2 == 1:
|
|
|
|
p = changebase(p, 16, 256)
|
|
|
|
self.assertEqual(p, decompress(compress(p)))
|
|
|
|
self.assertEqual(G[0], multiply(divide(G, x), x)[0])
|
|
|
|
|
|
|
|
|
|
|
|
class TestBases(unittest.TestCase):
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
print('Starting base change tests')
|
|
|
|
|
|
|
|
def test_all(self):
|
|
|
|
data = [
|
|
|
|
[10, '65535', 16, 'ffff'],
|
|
|
|
[16, 'deadbeef', 10, '3735928559'],
|
|
|
|
[10, '0', 16, ''],
|
|
|
|
[256, b'34567', 10, '219919234615'],
|
|
|
|
[10, '444', 16, '1bc'],
|
|
|
|
[256, b'\x03\x04\x05\x06\x07', 10, '12952339975'],
|
|
|
|
[16, '3132333435', 256, b'12345']
|
|
|
|
]
|
|
|
|
for prebase, preval, postbase, postval in data:
|
|
|
|
self.assertEqual(changebase(preval, prebase, postbase), postval)
|
|
|
|
|
|
|
|
for i in range(100):
|
|
|
|
x = random.randrange(1, 9999999999999999)
|
|
|
|
frm = random.choice([2, 10, 16, 58, 256])
|
|
|
|
to = random.choice([2, 10, 16, 58, 256])
|
|
|
|
self.assertEqual(decode(encode(x, to), to), x)
|
|
|
|
self.assertEqual(changebase(encode(x, frm), frm, to), encode(x, to))
|
|
|
|
self.assertEqual(decode(changebase(encode(x, frm), frm, to), to), x)
|
|
|
|
|
|
|
|
|
|
|
|
class TestElectrumWalletInternalConsistency(unittest.TestCase):
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
print('Starting Electrum wallet internal consistency tests')
|
|
|
|
|
|
|
|
def test_all(self):
|
|
|
|
for i in range(3):
|
|
|
|
seed = sha256(str(random.randrange(2**40)))[:32]
|
|
|
|
mpk = electrum_mpk(seed)
|
|
|
|
for i in range(5):
|
|
|
|
pk = electrum_privkey(seed, i)
|
|
|
|
pub = electrum_pubkey((mpk, seed)[i % 2], i)
|
|
|
|
pub2 = privtopub(pk)
|
|
|
|
self.assertEqual(
|
|
|
|
pub,
|
|
|
|
pub2,
|
|
|
|
'Does not match! Details:\nseed: %s\nmpk: %s\npriv: %s\npub: %s\npub2: %s' % (
|
|
|
|
seed, mpk, pk, pub, pub2
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2017-04-06 19:19:47 +02:00
|
|
|
class TestRawSignRecover(unittest.TestCase):
|
version 0.2.0, new lib for bitcoin ecc, dont display or track notify errors, dont reload again within 1 sec, null peer ip fix, signingmoved to ContentManager, content.json include support, content.json multisig ready, content.json proper bitcoincore compatible signing, content.json include permissions, multithreaded publish, publish timeout 60s, no exception on invalid bitcoin address, testcase for new lib, bip32 based persite privatekey generation, multiuser ready, simple json database query command, websocket api fileGet, wrapper loading title stuck bugfix
2015-02-09 02:09:02 +01:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
2017-04-06 19:19:47 +02:00
|
|
|
print("Basic signing and recovery tests")
|
version 0.2.0, new lib for bitcoin ecc, dont display or track notify errors, dont reload again within 1 sec, null peer ip fix, signingmoved to ContentManager, content.json include support, content.json multisig ready, content.json proper bitcoincore compatible signing, content.json include permissions, multithreaded publish, publish timeout 60s, no exception on invalid bitcoin address, testcase for new lib, bip32 based persite privatekey generation, multiuser ready, simple json database query command, websocket api fileGet, wrapper loading title stuck bugfix
2015-02-09 02:09:02 +01:00
|
|
|
|
2017-04-06 19:19:47 +02:00
|
|
|
def test_all(self):
|
|
|
|
for i in range(20):
|
|
|
|
k = sha256(str(i))
|
|
|
|
s = ecdsa_raw_sign('35' * 32, k)
|
version 0.2.0, new lib for bitcoin ecc, dont display or track notify errors, dont reload again within 1 sec, null peer ip fix, signingmoved to ContentManager, content.json include support, content.json multisig ready, content.json proper bitcoincore compatible signing, content.json include permissions, multithreaded publish, publish timeout 60s, no exception on invalid bitcoin address, testcase for new lib, bip32 based persite privatekey generation, multiuser ready, simple json database query command, websocket api fileGet, wrapper loading title stuck bugfix
2015-02-09 02:09:02 +01:00
|
|
|
self.assertEqual(
|
2017-04-06 19:19:47 +02:00
|
|
|
ecdsa_raw_recover('35' * 32, s),
|
|
|
|
decode_pubkey(privtopub(k))
|
version 0.2.0, new lib for bitcoin ecc, dont display or track notify errors, dont reload again within 1 sec, null peer ip fix, signingmoved to ContentManager, content.json include support, content.json multisig ready, content.json proper bitcoincore compatible signing, content.json include permissions, multithreaded publish, publish timeout 60s, no exception on invalid bitcoin address, testcase for new lib, bip32 based persite privatekey generation, multiuser ready, simple json database query command, websocket api fileGet, wrapper loading title stuck bugfix
2015-02-09 02:09:02 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
class TestTransactionSignVerify(unittest.TestCase):
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
print("Transaction-style signing and verification tests")
|
|
|
|
|
|
|
|
def test_all(self):
|
|
|
|
alphabet = "1234567890qwertyuiopasdfghjklzxcvbnm"
|
|
|
|
for i in range(10):
|
|
|
|
msg = ''.join([random.choice(alphabet) for i in range(random.randrange(20, 200))])
|
|
|
|
priv = sha256(str(random.randrange(2**256)))
|
|
|
|
pub = privtopub(priv)
|
|
|
|
sig = ecdsa_tx_sign(msg, priv)
|
|
|
|
self.assertTrue(
|
|
|
|
ecdsa_tx_verify(msg, sig, pub),
|
|
|
|
"Verification error"
|
|
|
|
)
|
|
|
|
|
|
|
|
self.assertIn(
|
|
|
|
pub,
|
|
|
|
ecdsa_tx_recover(msg, sig),
|
|
|
|
"Recovery failed"
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
class TestSerialize(unittest.TestCase):
|
|
|
|
|
|
|
|
def test_serialize(self):
|
|
|
|
tx = '0100000001239f932c780e517015842f3b02ff765fba97f9f63f9f1bc718b686a56ed9c73400000000fd5d010047304402200c40fa58d3f6d5537a343cf9c8d13bc7470baf1d13867e0de3e535cd6b4354c802200f2b48f67494835b060d0b2ff85657d2ba2d9ea4e697888c8cb580e8658183a801483045022056f488c59849a4259e7cef70fe5d6d53a4bd1c59a195b0577bd81cb76044beca022100a735b319fa66af7b178fc719b93f905961ef4d4446deca8757a90de2106dd98a014cc95241046c7d87fd72caeab48e937f2feca9e9a4bd77f0eff4ebb2dbbb9855c023e334e188d32aaec4632ea4cbc575c037d8101aec73d029236e7b1c2380f3e4ad7edced41046fd41cddf3bbda33a240b417a825cc46555949917c7ccf64c59f42fd8dfe95f34fae3b09ed279c8c5b3530510e8cca6230791102eef9961d895e8db54af0563c410488d618b988efd2511fc1f9c03f11c210808852b07fe46128c1a6b1155aa22cdf4b6802460ba593db2d11c7e6cbe19cedef76b7bcabd05d26fd97f4c5a59b225053aeffffffff0310270000000000001976a914a89733100315c37d228a529853af341a9d290a4588ac409c00000000000017a9142b56f9a4009d9ff99b8f97bea4455cd71135f5dd87409c00000000000017a9142b56f9a4009d9ff99b8f97bea4455cd71135f5dd8700000000'
|
|
|
|
self.assertEqual(
|
|
|
|
serialize(deserialize(tx)),
|
|
|
|
tx,
|
|
|
|
"Serialize roundtrip failed"
|
|
|
|
)
|
|
|
|
|
|
|
|
def test_serialize_script(self):
|
|
|
|
script = '47304402200c40fa58d3f6d5537a343cf9c8d13bc7470baf1d13867e0de3e535cd6b4354c802200f2b48f67494835b060d0b2ff85657d2ba2d9ea4e697888c8cb580e8658183a801483045022056f488c59849a4259e7cef70fe5d6d53a4bd1c59a195b0577bd81cb76044beca022100a735b319fa66af7b178fc719b93f905961ef4d4446deca8757a90de2106dd98a014cc95241046c7d87fd72caeab48e937f2feca9e9a4bd77f0eff4ebb2dbbb9855c023e334e188d32aaec4632ea4cbc575c037d8101aec73d029236e7b1c2380f3e4ad7edced41046fd41cddf3bbda33a240b417a825cc46555949917c7ccf64c59f42fd8dfe95f34fae3b09ed279c8c5b3530510e8cca6230791102eef9961d895e8db54af0563c410488d618b988efd2511fc1f9c03f11c210808852b07fe46128c1a6b1155aa22cdf4b6802460ba593db2d11c7e6cbe19cedef76b7bcabd05d26fd97f4c5a59b225053ae'
|
|
|
|
self.assertEqual(
|
|
|
|
serialize_script(deserialize_script(script)),
|
|
|
|
script,
|
|
|
|
"Script serialize roundtrip failed"
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
class TestTransaction(unittest.TestCase):
|
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
print("Attempting transaction creation")
|
|
|
|
|
|
|
|
# FIXME: I don't know how to write this as a unit test.
|
|
|
|
# What should be asserted?
|
|
|
|
def test_all(self):
|
|
|
|
privs = [sha256(str(random.randrange(2**256))) for x in range(4)]
|
|
|
|
pubs = [privtopub(priv) for priv in privs]
|
|
|
|
addresses = [pubtoaddr(pub) for pub in pubs]
|
|
|
|
mscript = mk_multisig_script(pubs[1:], 2, 3)
|
|
|
|
msigaddr = p2sh_scriptaddr(mscript)
|
|
|
|
tx = mktx(['01'*32+':1', '23'*32+':2'], [msigaddr+':20202', addresses[0]+':40404'])
|
|
|
|
tx1 = sign(tx, 1, privs[0])
|
|
|
|
|
|
|
|
sig1 = multisign(tx, 0, mscript, privs[1])
|
|
|
|
self.assertTrue(verify_tx_input(tx1, 0, mscript, sig1, pubs[1]), "Verification Error")
|
|
|
|
|
|
|
|
sig3 = multisign(tx, 0, mscript, privs[3])
|
|
|
|
self.assertTrue(verify_tx_input(tx1, 0, mscript, sig3, pubs[3]), "Verification Error")
|
|
|
|
|
|
|
|
tx2 = apply_multisignatures(tx1, 0, mscript, [sig1, sig3])
|
|
|
|
print("Outputting transaction: ", tx2)
|
|
|
|
|
Version 0.3.1, rev238, Connection encryption using TLS, One click site clone feature, Encryption stats, Disable encryption startup parameter, Disable ssl compression startup parameter, Exchange supported encryption methods at handshake, Alternative open port checker, Option to store site privatekey in users.json, Torrent tracker swap, Test for bip32 based site creation, cloning and sslcert creation, Fix for Chrome plugin on OSX, Separate siteSign websocket command, Update pybitcointools to major speedup, Re-add sslwrap for python 0.2.9+, Disable SSL compression to save memory and better performance
2015-06-10 00:29:30 +02:00
|
|
|
# https://github.com/vbuterin/pybitcointools/issues/71
|
|
|
|
def test_multisig(self):
|
|
|
|
script = mk_multisig_script(["0254236f7d1124fc07600ad3eec5ac47393bf963fbf0608bcce255e685580d16d9",
|
|
|
|
"03560cad89031c412ad8619398bd43b3d673cb5bdcdac1afc46449382c6a8e0b2b"],
|
|
|
|
2)
|
|
|
|
|
|
|
|
self.assertEqual(p2sh_scriptaddr(script), "33byJBaS5N45RHFcatTSt9ZjiGb6nK4iV3")
|
|
|
|
|
|
|
|
self.assertEqual(p2sh_scriptaddr(script, 0x05), "33byJBaS5N45RHFcatTSt9ZjiGb6nK4iV3")
|
|
|
|
self.assertEqual(p2sh_scriptaddr(script, 5), "33byJBaS5N45RHFcatTSt9ZjiGb6nK4iV3")
|
|
|
|
|
|
|
|
self.assertEqual(p2sh_scriptaddr(script, 0xc4), "2MuABMvWTgpZRd4tAG25KW6YzvcoGVZDZYP")
|
|
|
|
self.assertEqual(p2sh_scriptaddr(script, 196), "2MuABMvWTgpZRd4tAG25KW6YzvcoGVZDZYP")
|
|
|
|
|
version 0.2.0, new lib for bitcoin ecc, dont display or track notify errors, dont reload again within 1 sec, null peer ip fix, signingmoved to ContentManager, content.json include support, content.json multisig ready, content.json proper bitcoincore compatible signing, content.json include permissions, multithreaded publish, publish timeout 60s, no exception on invalid bitcoin address, testcase for new lib, bip32 based persite privatekey generation, multiuser ready, simple json database query command, websocket api fileGet, wrapper loading title stuck bugfix
2015-02-09 02:09:02 +01:00
|
|
|
|
|
|
|
class TestDeterministicGenerate(unittest.TestCase):
|
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
print("Beginning RFC6979 deterministic signing tests")
|
|
|
|
|
|
|
|
def test_all(self):
|
|
|
|
# Created with python-ecdsa 0.9
|
|
|
|
# Code to make your own vectors:
|
|
|
|
# class gen:
|
|
|
|
# def order(self): return 115792089237316195423570985008687907852837564279074904382605163141518161494337
|
|
|
|
# dummy = gen()
|
|
|
|
# for i in range(10): ecdsa.rfc6979.generate_k(dummy, i, hashlib.sha256, hashlib.sha256(str(i)).digest())
|
|
|
|
test_vectors = [
|
|
|
|
32783320859482229023646250050688645858316445811207841524283044428614360139869,
|
|
|
|
109592113955144883013243055602231029997040992035200230706187150761552110229971,
|
|
|
|
65765393578006003630736298397268097590176526363988568884298609868706232621488,
|
|
|
|
85563144787585457107933685459469453513056530050186673491900346620874099325918,
|
|
|
|
99829559501561741463404068005537785834525504175465914981205926165214632019533,
|
|
|
|
7755945018790142325513649272940177083855222863968691658328003977498047013576,
|
|
|
|
81516639518483202269820502976089105897400159721845694286620077204726637043798,
|
|
|
|
52824159213002398817852821148973968315579759063230697131029801896913602807019,
|
|
|
|
44033460667645047622273556650595158811264350043302911918907282441675680538675,
|
|
|
|
32396602643737403620316035551493791485834117358805817054817536312402837398361
|
|
|
|
]
|
|
|
|
|
|
|
|
for i, ti in enumerate(test_vectors):
|
|
|
|
mine = deterministic_generate_k(bin_sha256(str(i)), encode(i, 256, 32))
|
|
|
|
self.assertEqual(
|
|
|
|
ti,
|
|
|
|
mine,
|
|
|
|
"Test vector does not match. Details:\n%s\n%s" % (
|
|
|
|
ti,
|
|
|
|
mine
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
class TestBIP0032(unittest.TestCase):
|
|
|
|
"""See: https://en.bitcoin.it/wiki/BIP_0032"""
|
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
print("Beginning BIP0032 tests")
|
|
|
|
|
|
|
|
def _full_derive(self, key, chain):
|
|
|
|
if len(chain) == 0:
|
|
|
|
return key
|
|
|
|
elif chain[0] == 'pub':
|
|
|
|
return self._full_derive(bip32_privtopub(key), chain[1:])
|
|
|
|
else:
|
|
|
|
return self._full_derive(bip32_ckd(key, chain[0]), chain[1:])
|
|
|
|
|
|
|
|
def test_all(self):
|
|
|
|
test_vectors = [
|
|
|
|
[[], 'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi'],
|
|
|
|
[['pub'], 'xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8'],
|
|
|
|
[[2**31], 'xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7'],
|
|
|
|
[[2**31, 1], 'xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs'],
|
|
|
|
[[2**31, 1, 2**31 + 2], 'xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM'],
|
|
|
|
[[2**31, 1, 2**31 + 2, 'pub', 2, 1000000000], 'xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy']
|
|
|
|
]
|
|
|
|
|
|
|
|
mk = bip32_master_key(safe_from_hex('000102030405060708090a0b0c0d0e0f'))
|
|
|
|
|
|
|
|
for tv in test_vectors:
|
|
|
|
left, right = self._full_derive(mk, tv[0]), tv[1]
|
|
|
|
self.assertEqual(
|
|
|
|
left,
|
|
|
|
right,
|
2019-01-06 15:15:47 +01:00
|
|
|
r"Test vector does not match. Details: \n%s\n%s\n\%s" % (
|
version 0.2.0, new lib for bitcoin ecc, dont display or track notify errors, dont reload again within 1 sec, null peer ip fix, signingmoved to ContentManager, content.json include support, content.json multisig ready, content.json proper bitcoincore compatible signing, content.json include permissions, multithreaded publish, publish timeout 60s, no exception on invalid bitcoin address, testcase for new lib, bip32 based persite privatekey generation, multiuser ready, simple json database query command, websocket api fileGet, wrapper loading title stuck bugfix
2015-02-09 02:09:02 +01:00
|
|
|
tv[0],
|
|
|
|
[x.encode('hex') if isinstance(x, str) else x for x in bip32_deserialize(left)],
|
|
|
|
[x.encode('hex') if isinstance(x, str) else x for x in bip32_deserialize(right)],
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
Version 0.3.1, rev238, Connection encryption using TLS, One click site clone feature, Encryption stats, Disable encryption startup parameter, Disable ssl compression startup parameter, Exchange supported encryption methods at handshake, Alternative open port checker, Option to store site privatekey in users.json, Torrent tracker swap, Test for bip32 based site creation, cloning and sslcert creation, Fix for Chrome plugin on OSX, Separate siteSign websocket command, Update pybitcointools to major speedup, Re-add sslwrap for python 0.2.9+, Disable SSL compression to save memory and better performance
2015-06-10 00:29:30 +02:00
|
|
|
def test_all_testnet(self):
|
|
|
|
test_vectors = [
|
|
|
|
[[], 'tprv8ZgxMBicQKsPeDgjzdC36fs6bMjGApWDNLR9erAXMs5skhMv36j9MV5ecvfavji5khqjWaWSFhN3YcCUUdiKH6isR4Pwy3U5y5egddBr16m'],
|
|
|
|
[['pub'], 'tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp'],
|
|
|
|
[[2**31], 'tprv8bxNLu25VazNnppTCP4fyhyCvBHcYtzE3wr3cwYeL4HA7yf6TLGEUdS4QC1vLT63TkjRssqJe4CvGNEC8DzW5AoPUw56D1Ayg6HY4oy8QZ9'],
|
|
|
|
[[2**31, 1], 'tprv8e8VYgZxtHsSdGrtvdxYaSrryZGiYviWzGWtDDKTGh5NMXAEB8gYSCLHpFCywNs5uqV7ghRjimALQJkRFZnUrLHpzi2pGkwqLtbubgWuQ8q'],
|
|
|
|
[[2**31, 1, 2**31 + 2], 'tprv8gjmbDPpbAirVSezBEMuwSu1Ci9EpUJWKokZTYccSZSomNMLytWyLdtDNHRbucNaRJWWHANf9AzEdWVAqahfyRjVMKbNRhBmxAM8EJr7R15'],
|
|
|
|
[[2**31, 1, 2**31 + 2, 'pub', 2, 1000000000], 'tpubDHNy3kAG39ThyiwwsgoKY4iRenXDRtce8qdCFJZXPMCJg5dsCUHayp84raLTpvyiNA9sXPob5rgqkKvkN8S7MMyXbnEhGJMW64Cf4vFAoaF']
|
|
|
|
]
|
|
|
|
|
|
|
|
mk = bip32_master_key(safe_from_hex('000102030405060708090a0b0c0d0e0f'), TESTNET_PRIVATE)
|
|
|
|
|
|
|
|
for tv in test_vectors:
|
|
|
|
left, right = self._full_derive(mk, tv[0]), tv[1]
|
|
|
|
self.assertEqual(
|
|
|
|
left,
|
|
|
|
right,
|
2019-01-06 15:15:47 +01:00
|
|
|
r"Test vector does not match. Details:\n%s\n%s\n%s\n\%s" % (
|
Version 0.3.1, rev238, Connection encryption using TLS, One click site clone feature, Encryption stats, Disable encryption startup parameter, Disable ssl compression startup parameter, Exchange supported encryption methods at handshake, Alternative open port checker, Option to store site privatekey in users.json, Torrent tracker swap, Test for bip32 based site creation, cloning and sslcert creation, Fix for Chrome plugin on OSX, Separate siteSign websocket command, Update pybitcointools to major speedup, Re-add sslwrap for python 0.2.9+, Disable SSL compression to save memory and better performance
2015-06-10 00:29:30 +02:00
|
|
|
left,
|
|
|
|
tv[0],
|
|
|
|
[x.encode('hex') if isinstance(x, str) else x for x in bip32_deserialize(left)],
|
|
|
|
[x.encode('hex') if isinstance(x, str) else x for x in bip32_deserialize(right)],
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
def test_extra(self):
|
|
|
|
master = bip32_master_key(safe_from_hex("000102030405060708090a0b0c0d0e0f"))
|
|
|
|
|
|
|
|
# m/0
|
|
|
|
assert bip32_ckd(master, "0") == "xprv9uHRZZhbkedL37eZEnyrNsQPFZYRAvjy5rt6M1nbEkLSo378x1CQQLo2xxBvREwiK6kqf7GRNvsNEchwibzXaV6i5GcsgyjBeRguXhKsi4R"
|
|
|
|
assert bip32_privtopub(bip32_ckd(master, "0")) == "xpub68Gmy5EVb2BdFbj2LpWrk1M7obNuaPTpT5oh9QCCo5sRfqSHVYWex97WpDZzszdzHzxXDAzPLVSwybe4uPYkSk4G3gnrPqqkV9RyNzAcNJ1"
|
|
|
|
|
|
|
|
# m/1
|
|
|
|
assert bip32_ckd(master, "1") == "xprv9uHRZZhbkedL4yTpidDvuVfrdUkTbhDHviERRBkbzbNDZeMjWzqzKAdxWhzftGDSxDmBdakjqHiZJbkwiaTEXJdjZAaAjMZEE3PMbMrPJih"
|
|
|
|
assert bip32_privtopub(bip32_ckd(master, "1")) == "xpub68Gmy5EVb2BdHTYHpekwGdcbBWax19w9HwA2DaADYvuCSSgt4YAErxxSN1KWSnmyqkwRNbnTj3XiUBKmHeC8rTjLRPjSULcDKQQgfgJDppq"
|
|
|
|
|
|
|
|
# m/0/0
|
|
|
|
assert bip32_ckd(bip32_ckd(master, "0"), "0") == "xprv9ww7sMFLzJMzur2oEQDB642fbsMS4q6JRraMVTrM9bTWBq7NDS8ZpmsKVB4YF3mZecqax1fjnsPF19xnsJNfRp4RSyexacULXMKowSACTRc"
|
|
|
|
assert bip32_privtopub(bip32_ckd(bip32_ckd(master, "0"), "0")) == "xpub6AvUGrnEpfvJ8L7GLRkBTByQ9uBvUHp9o5VxHrFxhvzV4dSWkySpNaBoLR9FpbnwRmTa69yLHF3QfcaxbWT7gWdwws5k4dpmJvqpEuMWwnj"
|
|
|
|
|
|
|
|
# m/0'
|
|
|
|
assert bip32_ckd(master, 2**31) == "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7"
|
|
|
|
assert bip32_privtopub(bip32_ckd(master, 2**31)) == "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw"
|
|
|
|
|
|
|
|
# m/1'
|
|
|
|
assert bip32_ckd(master, 2**31 + 1) == "xprv9uHRZZhk6KAJFszJGW6LoUFq92uL7FvkBhmYiMurCWPHLJZkX2aGvNdRUBNnJu7nv36WnwCN59uNy6sxLDZvvNSgFz3TCCcKo7iutQzpg78"
|
|
|
|
assert bip32_privtopub(bip32_ckd(master, 2**31 + 1)) == "xpub68Gmy5EdvgibUN4mNXdMAcCZh4jpWiebYvh9WkKTkqvGD6tu4ZtXUAwuKSyF5DFZVmotf9UHFTGqSXo9qyDBSn47RkaN6Aedt9JbL7zcgSL"
|
|
|
|
|
|
|
|
# m/1'
|
|
|
|
assert bip32_ckd(master, 1 + 2**31) == "xprv9uHRZZhk6KAJFszJGW6LoUFq92uL7FvkBhmYiMurCWPHLJZkX2aGvNdRUBNnJu7nv36WnwCN59uNy6sxLDZvvNSgFz3TCCcKo7iutQzpg78"
|
|
|
|
assert bip32_privtopub(bip32_ckd(master, 1 + 2**31)) == "xpub68Gmy5EdvgibUN4mNXdMAcCZh4jpWiebYvh9WkKTkqvGD6tu4ZtXUAwuKSyF5DFZVmotf9UHFTGqSXo9qyDBSn47RkaN6Aedt9JbL7zcgSL"
|
|
|
|
|
|
|
|
# m/0'/0
|
|
|
|
assert bip32_ckd(bip32_ckd(master, 2**31), "0") == "xprv9wTYmMFdV23N21MM6dLNavSQV7Sj7meSPXx6AV5eTdqqGLjycVjb115Ec5LgRAXscPZgy5G4jQ9csyyZLN3PZLxoM1h3BoPuEJzsgeypdKj"
|
|
|
|
assert bip32_privtopub(bip32_ckd(bip32_ckd(master, 2**31), "0")) == "xpub6ASuArnXKPbfEVRpCesNx4P939HDXENHkksgxsVG1yNp9958A33qYoPiTN9QrJmWFa2jNLdK84bWmyqTSPGtApP8P7nHUYwxHPhqmzUyeFG"
|
|
|
|
|
|
|
|
# m/0'/0'
|
|
|
|
assert bip32_ckd(bip32_ckd(master, 2**31), 2**31) == "xprv9wTYmMFmpgaLB5Hge4YtaGqCKpsYPTD9vXWSsmdZrNU3Y2i4WoBykm6ZteeCLCCZpGxdHQuqEhM6Gdo2X6CVrQiTw6AAneF9WSkA9ewaxtS"
|
|
|
|
assert bip32_privtopub(bip32_ckd(bip32_ckd(master, 2**31), 2**31)) == "xpub6ASuArnff48dPZN9k65twQmvsri2nuw1HkS3gA3BQi12Qq3D4LWEJZR3jwCAr1NhsFMcQcBkmevmub6SLP37bNq91SEShXtEGUbX3GhNaGk"
|
|
|
|
|
|
|
|
# m/44'/0'/0'/0/0
|
|
|
|
assert bip32_ckd(bip32_ckd(bip32_ckd(bip32_ckd(bip32_ckd(master, 44 + 2**31), 2**31), 2**31), 0), 0) == "xprvA4A9CuBXhdBtCaLxwrw64Jaran4n1rgzeS5mjH47Ds8V67uZS8tTkG8jV3BZi83QqYXPcN4v8EjK2Aof4YcEeqLt688mV57gF4j6QZWdP9U"
|
|
|
|
assert bip32_privtopub(bip32_ckd(bip32_ckd(bip32_ckd(bip32_ckd(bip32_ckd(master, 44 + 2**31), 2**31), 2**31), 0), 0)) == "xpub6H9VcQiRXzkBR4RS3tU6RSXb8ouGRKQr1f1NXfTinCfTxvEhygCiJ4TDLHz1dyQ6d2Vz8Ne7eezkrViwaPo2ZMsNjVtFwvzsQXCDV6HJ3cV"
|
|
|
|
|
version 0.2.0, new lib for bitcoin ecc, dont display or track notify errors, dont reload again within 1 sec, null peer ip fix, signingmoved to ContentManager, content.json include support, content.json multisig ready, content.json proper bitcoincore compatible signing, content.json include permissions, multithreaded publish, publish timeout 60s, no exception on invalid bitcoin address, testcase for new lib, bip32 based persite privatekey generation, multiuser ready, simple json database query command, websocket api fileGet, wrapper loading title stuck bugfix
2015-02-09 02:09:02 +01:00
|
|
|
|
|
|
|
class TestStartingAddressAndScriptGenerationConsistency(unittest.TestCase):
|
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
print("Starting address and script generation consistency tests")
|
|
|
|
|
|
|
|
def test_all(self):
|
|
|
|
for i in range(5):
|
|
|
|
a = privtoaddr(random_key())
|
|
|
|
self.assertEqual(a, script_to_address(address_to_script(a)))
|
Version 0.3.1, rev238, Connection encryption using TLS, One click site clone feature, Encryption stats, Disable encryption startup parameter, Disable ssl compression startup parameter, Exchange supported encryption methods at handshake, Alternative open port checker, Option to store site privatekey in users.json, Torrent tracker swap, Test for bip32 based site creation, cloning and sslcert creation, Fix for Chrome plugin on OSX, Separate siteSign websocket command, Update pybitcointools to major speedup, Re-add sslwrap for python 0.2.9+, Disable SSL compression to save memory and better performance
2015-06-10 00:29:30 +02:00
|
|
|
self.assertEqual(a, script_to_address(address_to_script(a), 0))
|
|
|
|
self.assertEqual(a, script_to_address(address_to_script(a), 0x00))
|
|
|
|
|
version 0.2.0, new lib for bitcoin ecc, dont display or track notify errors, dont reload again within 1 sec, null peer ip fix, signingmoved to ContentManager, content.json include support, content.json multisig ready, content.json proper bitcoincore compatible signing, content.json include permissions, multithreaded publish, publish timeout 60s, no exception on invalid bitcoin address, testcase for new lib, bip32 based persite privatekey generation, multiuser ready, simple json database query command, websocket api fileGet, wrapper loading title stuck bugfix
2015-02-09 02:09:02 +01:00
|
|
|
b = privtoaddr(random_key(), 5)
|
|
|
|
self.assertEqual(b, script_to_address(address_to_script(b)))
|
Version 0.3.1, rev238, Connection encryption using TLS, One click site clone feature, Encryption stats, Disable encryption startup parameter, Disable ssl compression startup parameter, Exchange supported encryption methods at handshake, Alternative open port checker, Option to store site privatekey in users.json, Torrent tracker swap, Test for bip32 based site creation, cloning and sslcert creation, Fix for Chrome plugin on OSX, Separate siteSign websocket command, Update pybitcointools to major speedup, Re-add sslwrap for python 0.2.9+, Disable SSL compression to save memory and better performance
2015-06-10 00:29:30 +02:00
|
|
|
self.assertEqual(b, script_to_address(address_to_script(b), 0))
|
|
|
|
self.assertEqual(b, script_to_address(address_to_script(b), 0x00))
|
|
|
|
self.assertEqual(b, script_to_address(address_to_script(b), 5))
|
|
|
|
self.assertEqual(b, script_to_address(address_to_script(b), 0x05))
|
|
|
|
|
|
|
|
|
|
|
|
for i in range(5):
|
|
|
|
a = privtoaddr(random_key(), 0x6f)
|
|
|
|
self.assertEqual(a, script_to_address(address_to_script(a), 111))
|
|
|
|
self.assertEqual(a, script_to_address(address_to_script(a), 0x6f))
|
|
|
|
|
|
|
|
b = privtoaddr(random_key(), 0xc4)
|
|
|
|
self.assertEqual(b, script_to_address(address_to_script(b), 111))
|
|
|
|
self.assertEqual(b, script_to_address(address_to_script(b), 0x6f))
|
|
|
|
self.assertEqual(b, script_to_address(address_to_script(b), 196))
|
|
|
|
self.assertEqual(b, script_to_address(address_to_script(b), 0xc4))
|
version 0.2.0, new lib for bitcoin ecc, dont display or track notify errors, dont reload again within 1 sec, null peer ip fix, signingmoved to ContentManager, content.json include support, content.json multisig ready, content.json proper bitcoincore compatible signing, content.json include permissions, multithreaded publish, publish timeout 60s, no exception on invalid bitcoin address, testcase for new lib, bip32 based persite privatekey generation, multiuser ready, simple json database query command, websocket api fileGet, wrapper loading title stuck bugfix
2015-02-09 02:09:02 +01:00
|
|
|
|
|
|
|
|
|
|
|
class TestRipeMD160PythonBackup(unittest.TestCase):
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
print('Testing the pure python backup for ripemd160')
|
|
|
|
|
|
|
|
def test_all(self):
|
|
|
|
strvec = [
|
|
|
|
'',
|
|
|
|
'The quick brown fox jumps over the lazy dog',
|
|
|
|
'The quick brown fox jumps over the lazy cog',
|
|
|
|
'Nobody inspects the spammish repetition'
|
|
|
|
]
|
|
|
|
|
|
|
|
target = [
|
|
|
|
'9c1185a5c5e9fc54612808977ee8f548b2258d31',
|
|
|
|
'37f332f68db77bd9d7edd4969571ad671cf9dd3b',
|
|
|
|
'132072df690933835eb8b6ad0b77e7b6f14acad7',
|
|
|
|
'cc4a5ce1b3df48aec5d22d1f16b894a0b894eccc'
|
|
|
|
]
|
|
|
|
|
|
|
|
hash160target = [
|
|
|
|
'b472a266d0bd89c13706a4132ccfb16f7c3b9fcb',
|
|
|
|
'0e3397b4abc7a382b3ea2365883c3c7ca5f07600',
|
|
|
|
'53e0dacac5249e46114f65cb1f30d156b14e0bdc',
|
|
|
|
'1c9b7b48049a8f98699bca22a5856c5ef571cd68'
|
|
|
|
]
|
|
|
|
|
|
|
|
for i, s in enumerate(strvec):
|
|
|
|
digest = ripemd.RIPEMD160(s).digest()
|
|
|
|
hash160digest = ripemd.RIPEMD160(bin_sha256(s)).digest()
|
|
|
|
self.assertEqual(bytes_to_hex_string(digest), target[i])
|
|
|
|
self.assertEqual(bytes_to_hex_string(hash160digest), hash160target[i])
|
|
|
|
self.assertEqual(bytes_to_hex_string(bin_hash160(from_string_to_bytes(s))), hash160target[i])
|
|
|
|
self.assertEqual(hash160(from_string_to_bytes(s)), hash160target[i])
|
|
|
|
|
|
|
|
|
|
|
|
class TestScriptVsAddressOutputs(unittest.TestCase):
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
print('Testing script vs address outputs')
|
|
|
|
|
|
|
|
def test_all(self):
|
|
|
|
addr0 = '1Lqgj1ThNfwLgHMp5qJUerYsuUEm8vHmVG'
|
|
|
|
script0 = '76a914d99f84267d1f90f3e870a5e9d2399918140be61d88ac'
|
|
|
|
addr1 = '31oSGBBNrpCiENH3XMZpiP6GTC4tad4bMy'
|
|
|
|
script1 = 'a9140136d001619faba572df2ef3d193a57ad29122d987'
|
|
|
|
|
|
|
|
inputs = [{
|
|
|
|
'output': 'cd6219ea108119dc62fce09698b649efde56eca7ce223a3315e8b431f6280ce7:0',
|
|
|
|
'value': 158000
|
|
|
|
}]
|
|
|
|
|
|
|
|
outputs = [
|
|
|
|
[{'address': addr0, 'value': 1000}, {'address': addr1, 'value': 2000}],
|
|
|
|
[{'script': script0, 'value': 1000}, {'address': addr1, 'value': 2000}],
|
|
|
|
[{'address': addr0, 'value': 1000}, {'script': script1, 'value': 2000}],
|
|
|
|
[{'script': script0, 'value': 1000}, {'script': script1, 'value': 2000}],
|
|
|
|
[addr0 + ':1000', addr1 + ':2000'],
|
|
|
|
[script0 + ':1000', addr1 + ':2000'],
|
|
|
|
[addr0 + ':1000', script1 + ':2000'],
|
|
|
|
[script0 + ':1000', script1 + ':2000']
|
|
|
|
]
|
|
|
|
|
|
|
|
for outs in outputs:
|
|
|
|
tx_struct = deserialize(mktx(inputs, outs))
|
|
|
|
self.assertEqual(tx_struct['outs'], outputs[3])
|
|
|
|
|
|
|
|
|
|
|
|
class TestConversions(unittest.TestCase):
|
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
cls.privkey_hex = (
|
|
|
|
"e9873d79c6d87dc0fb6a5778633389f4453213303da61f20bd67fc233aa33262"
|
|
|
|
)
|
|
|
|
cls.privkey_bin = (
|
|
|
|
b"\xe9\x87=y\xc6\xd8}\xc0\xfbjWxc3\x89\xf4E2\x130=\xa6\x1f \xbdg\xfc#:\xa32b"
|
|
|
|
)
|
|
|
|
|
|
|
|
cls.pubkey_hex = (
|
|
|
|
"04588d202afcc1ee4ab5254c7847ec25b9a135bbda0f2bc69ee1a714749fd77dc9f88ff2a00d7e752d44cbe16e1ebcf0890b76ec7c78886109dee76ccfc8445424"
|
|
|
|
)
|
|
|
|
cls.pubkey_bin = (
|
|
|
|
b"\x04X\x8d *\xfc\xc1\xeeJ\xb5%LxG\xec%\xb9\xa15\xbb\xda\x0f+\xc6\x9e\xe1\xa7\x14t\x9f\xd7}\xc9\xf8\x8f\xf2\xa0\r~u-D\xcb\xe1n\x1e\xbc\xf0\x89\x0bv\xec|x\x88a\t\xde\xe7l\xcf\xc8DT$"
|
|
|
|
)
|
|
|
|
|
|
|
|
def test_privkey_to_pubkey(self):
|
|
|
|
pubkey_hex = privkey_to_pubkey(self.privkey_hex)
|
|
|
|
self.assertEqual(pubkey_hex, self.pubkey_hex)
|
|
|
|
|
|
|
|
def test_changebase(self):
|
|
|
|
self.assertEqual(
|
|
|
|
self.pubkey_bin,
|
|
|
|
changebase(
|
|
|
|
self.pubkey_hex, 16, 256, minlen=len(self.pubkey_bin)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
self.pubkey_hex,
|
|
|
|
changebase(
|
|
|
|
self.pubkey_bin, 256, 16, minlen=len(self.pubkey_hex)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
self.privkey_bin,
|
|
|
|
changebase(
|
|
|
|
self.privkey_hex, 16, 256, minlen=len(self.privkey_bin)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
self.privkey_hex,
|
|
|
|
changebase(
|
|
|
|
self.privkey_bin, 256, 16, minlen=len(self.privkey_hex)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
unittest.main()
|