test: add tests/ folder with SecretScan verification links

- Add pytest test suite for all 5 address types (P2PK, P2PKH, P2SH, P2WPKH, P2TR)
- Test output fields, address prefixes per network, key lengths and uniqueness
- Each test file prints the SecretScan URL for manual address verification
- Add pytest to requirements.txt
This commit is contained in:
2026-03-09 11:11:41 +01:00
parent 290c371169
commit 409669e000
7 changed files with 330 additions and 0 deletions

0
tests/__init__.py Normal file
View File

67
tests/test_p2pk.py Normal file
View File

@@ -0,0 +1,67 @@
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from src.p2pk import generate_p2pk
SECRETSCAN_URL = "https://secretscan.org/Bitcoin?address={}"
NETWORKS = ['mainnet', 'testnet', 'regtest']
def test_p2pk_fields():
result = generate_p2pk('mainnet', compressed=True)
assert set(result.keys()) == {'network', 'script_type', 'private_key_hex', 'private_key_wif', 'public_key_hex'}
def test_p2pk_script_type():
result = generate_p2pk('mainnet')
assert result['script_type'] == 'p2pk'
def test_p2pk_private_key_length():
result = generate_p2pk('mainnet')
assert len(result['private_key_hex']) == 64
def test_p2pk_compressed_pubkey_length():
result = generate_p2pk('mainnet', compressed=True)
assert len(result['public_key_hex']) == 66
assert result['public_key_hex'][:2] in ('02', '03')
def test_p2pk_uncompressed_pubkey_length():
result = generate_p2pk('mainnet', compressed=False)
assert len(result['public_key_hex']) == 130
assert result['public_key_hex'][:2] == '04'
def test_p2pk_wif_mainnet():
result = generate_p2pk('mainnet', compressed=True)
assert result['private_key_wif'][0] in ('K', 'L')
def test_p2pk_wif_testnet():
result = generate_p2pk('testnet', compressed=True)
assert result['private_key_wif'][0] == 'c'
def test_p2pk_all_networks():
for network in NETWORKS:
result = generate_p2pk(network)
assert result['network'] == network
def test_p2pk_unique_keys():
r1 = generate_p2pk('mainnet')
r2 = generate_p2pk('mainnet')
assert r1['private_key_hex'] != r2['private_key_hex']
def test_p2pk_print_secretscan(capsys):
# P2PK has no address — print the public key for manual reference
result = generate_p2pk('mainnet')
print(f"\n[P2PK] Public key: {result['public_key_hex']}")
print(f"[P2PK] SecretScan (search by pubkey): https://secretscan.org/")
captured = capsys.readouterr()
assert 'secretscan.org' in captured.out

66
tests/test_p2pkh.py Normal file
View File

@@ -0,0 +1,66 @@
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from src.p2pkh import generate_legacy_address
SECRETSCAN_URL = "https://secretscan.org/Bitcoin?address={}"
NETWORKS = ['mainnet', 'testnet', 'regtest']
def test_p2pkh_fields():
result = generate_legacy_address('mainnet')
assert set(result.keys()) == {'network', 'script_type', 'private_key_hex', 'private_key_wif', 'public_key_hex', 'address'}
def test_p2pkh_script_type():
result = generate_legacy_address('mainnet')
assert result['script_type'] == 'p2pkh'
def test_p2pkh_address_mainnet():
result = generate_legacy_address('mainnet')
assert result['address'].startswith('1')
def test_p2pkh_address_testnet():
result = generate_legacy_address('testnet')
assert result['address'][0] in ('m', 'n')
def test_p2pkh_address_regtest():
result = generate_legacy_address('regtest')
assert result['address'][0] in ('m', 'n')
def test_p2pkh_private_key_length():
result = generate_legacy_address('mainnet')
assert len(result['private_key_hex']) == 64
def test_p2pkh_compressed_pubkey():
result = generate_legacy_address('mainnet', compressed=True)
assert len(result['public_key_hex']) == 66
assert result['public_key_hex'][:2] in ('02', '03')
def test_p2pkh_uncompressed_pubkey():
result = generate_legacy_address('mainnet', compressed=False)
assert len(result['public_key_hex']) == 130
assert result['public_key_hex'][:2] == '04'
def test_p2pkh_unique_addresses():
r1 = generate_legacy_address('mainnet')
r2 = generate_legacy_address('mainnet')
assert r1['address'] != r2['address']
def test_p2pkh_print_secretscan(capsys):
result = generate_legacy_address('mainnet')
url = SECRETSCAN_URL.format(result['address'])
print(f"\n[P2PKH] Address: {result['address']}")
print(f"[P2PKH] Verify on SecretScan: {url}")
captured = capsys.readouterr()
assert 'secretscan.org' in captured.out

77
tests/test_p2sh.py Normal file
View File

@@ -0,0 +1,77 @@
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from src.p2sh import generate_p2sh_multisig
SECRETSCAN_URL = "https://secretscan.org/Bitcoin?address={}"
NETWORKS = ['mainnet', 'testnet', 'regtest']
def test_p2sh_fields():
result = generate_p2sh_multisig('mainnet', m=2, n=3)
assert set(result.keys()) == {'network', 'script_type', 'm', 'n', 'redeem_script_hex', 'participants', 'address'}
def test_p2sh_script_type():
result = generate_p2sh_multisig('mainnet', m=2, n=3)
assert result['script_type'] == 'p2sh-multisig'
def test_p2sh_address_mainnet():
result = generate_p2sh_multisig('mainnet', m=2, n=3)
assert result['address'].startswith('3')
def test_p2sh_address_testnet():
result = generate_p2sh_multisig('testnet', m=2, n=3)
assert result['address'].startswith('2')
def test_p2sh_address_regtest():
result = generate_p2sh_multisig('regtest', m=2, n=3)
assert result['address'].startswith('2')
def test_p2sh_participants_count():
result = generate_p2sh_multisig('mainnet', m=2, n=3)
assert len(result['participants']) == 3
assert result['m'] == 2
assert result['n'] == 3
def test_p2sh_participant_fields():
result = generate_p2sh_multisig('mainnet', m=2, n=3)
for p in result['participants']:
assert 'private_key_hex' in p
assert 'private_key_wif' in p
assert 'public_key_hex' in p
assert len(p['private_key_hex']) == 64
def test_p2sh_redeem_script_not_empty():
result = generate_p2sh_multisig('mainnet', m=2, n=3)
assert len(result['redeem_script_hex']) > 0
def test_p2sh_1of1():
result = generate_p2sh_multisig('mainnet', m=1, n=1)
assert result['m'] == 1
assert result['n'] == 1
assert len(result['participants']) == 1
def test_p2sh_unique_addresses():
r1 = generate_p2sh_multisig('mainnet', m=2, n=3)
r2 = generate_p2sh_multisig('mainnet', m=2, n=3)
assert r1['address'] != r2['address']
def test_p2sh_print_secretscan(capsys):
result = generate_p2sh_multisig('mainnet', m=2, n=3)
url = SECRETSCAN_URL.format(result['address'])
print(f"\n[P2SH] Address: {result['address']}")
print(f"[P2SH] Verify on SecretScan: {url}")
captured = capsys.readouterr()
assert 'secretscan.org' in captured.out

59
tests/test_p2tr.py Normal file
View File

@@ -0,0 +1,59 @@
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from src.p2tr import generate_p2tr_address
SECRETSCAN_URL = "https://secretscan.org/Bitcoin?address={}"
NETWORKS = ['mainnet', 'testnet', 'regtest']
def test_p2tr_fields():
result = generate_p2tr_address('mainnet')
assert set(result.keys()) == {'network', 'script_type', 'private_key_hex', 'private_key_wif', 'internal_pubkey_x_hex', 'address'}
def test_p2tr_script_type():
result = generate_p2tr_address('mainnet')
assert result['script_type'] == 'p2tr'
def test_p2tr_address_mainnet():
result = generate_p2tr_address('mainnet')
assert result['address'].startswith('bc1p')
def test_p2tr_address_testnet():
result = generate_p2tr_address('testnet')
assert result['address'].startswith('tb1p')
def test_p2tr_address_regtest():
result = generate_p2tr_address('regtest')
assert result['address'].startswith('bcrt1p')
def test_p2tr_private_key_length():
result = generate_p2tr_address('mainnet')
assert len(result['private_key_hex']) == 64
def test_p2tr_internal_pubkey_length():
result = generate_p2tr_address('mainnet')
assert len(result['internal_pubkey_x_hex']) == 64 # x-only pubkey, 32 bytes
def test_p2tr_unique_addresses():
r1 = generate_p2tr_address('mainnet')
r2 = generate_p2tr_address('mainnet')
assert r1['address'] != r2['address']
def test_p2tr_print_secretscan(capsys):
result = generate_p2tr_address('mainnet')
url = SECRETSCAN_URL.format(result['address'])
print(f"\n[P2TR] Address: {result['address']}")
print(f"[P2TR] Verify on SecretScan: {url}")
captured = capsys.readouterr()
assert 'secretscan.org' in captured.out

60
tests/test_p2wpkh.py Normal file
View File

@@ -0,0 +1,60 @@
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from src.p2wpkh import generate_segwit_address
SECRETSCAN_URL = "https://secretscan.org/Bitcoin?address={}"
NETWORKS = ['mainnet', 'testnet', 'regtest']
def test_p2wpkh_fields():
result = generate_segwit_address('mainnet')
assert set(result.keys()) == {'network', 'script_type', 'private_key_hex', 'private_key_wif', 'public_key_hex', 'address'}
def test_p2wpkh_script_type():
result = generate_segwit_address('mainnet')
assert result['script_type'] == 'p2wpkh'
def test_p2wpkh_address_mainnet():
result = generate_segwit_address('mainnet')
assert result['address'].startswith('bc1q')
def test_p2wpkh_address_testnet():
result = generate_segwit_address('testnet')
assert result['address'].startswith('tb1q')
def test_p2wpkh_address_regtest():
result = generate_segwit_address('regtest')
assert result['address'].startswith('bcrt1q')
def test_p2wpkh_private_key_length():
result = generate_segwit_address('mainnet')
assert len(result['private_key_hex']) == 64
def test_p2wpkh_compressed_pubkey():
result = generate_segwit_address('mainnet', compressed=True)
assert len(result['public_key_hex']) == 66
assert result['public_key_hex'][:2] in ('02', '03')
def test_p2wpkh_unique_addresses():
r1 = generate_segwit_address('mainnet')
r2 = generate_segwit_address('mainnet')
assert r1['address'] != r2['address']
def test_p2wpkh_print_secretscan(capsys):
result = generate_segwit_address('mainnet')
url = SECRETSCAN_URL.format(result['address'])
print(f"\n[P2WPKH] Address: {result['address']}")
print(f"[P2WPKH] Verify on SecretScan: {url}")
captured = capsys.readouterr()
assert 'secretscan.org' in captured.out