#!/usr/bin/env python3 """ Bootstrap script to generate tests/vectors.json. Run this ONCE (online allowed if needed, though this logic is offline) to freeze the expected outputs of the current pyhdwallet implementation. """ import sys import json import os from pathlib import Path # Add src to path so we can import pyhdwallet sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "../src"))) import pyhdwallet from bip_utils import Bip39SeedGenerator def main(): print("Bootstrapping test vectors...") vectors = {} # 1. PGP Fingerprint Vector recipient_path = Path(__file__).parent / "data" / "recipient.asc" if not recipient_path.exists(): print(f"Error: {recipient_path} not found. Please create it first.") sys.exit(1) with open(recipient_path, "r", encoding="utf-8") as f: armored = f.read() # Calculate expected fingerprint using current code logic expected_fpr = pyhdwallet.pgp_fingerprint(armored) vectors["pgp"] = { "recipient_file": "recipient.asc", "expected_fingerprint": expected_fpr } print(f"PGP: Pinned fingerprint {expected_fpr}") # 2. BIP39 & Derivation Vectors mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" vectors["bip39"] = [] # Case A: No Passphrase seed_bytes = Bip39SeedGenerator(mnemonic).Generate("") seed_hex = seed_bytes.hex() # Generate addresses for all supported chains/profiles chains = ["ethereum", "bitcoin", "solana"] # Fixed profile names to use underscores instead of hyphens sol_profiles = ["phantom_bip44change", "phantom_bip44", "solana_bip39_first32"] derived_data = {} # Run derivation for each sol profile logic for profile in sol_profiles: res = pyhdwallet.derive_all( seed_bytes, chains, count=5, sol_profile=profile, export_private=False ) derived_data[profile] = res["addresses"] vectors["bip39"].append({ "mnemonic": mnemonic, "passphrase": "", "expected_seed_hex": seed_hex, "derived_addresses": derived_data }) # Case B: With Passphrase (Regression test) passphrase = "TREZOR" seed_bytes_p = Bip39SeedGenerator(mnemonic).Generate(passphrase) seed_hex_p = seed_bytes_p.hex() res_p = pyhdwallet.derive_all( seed_bytes_p, chains, count=1, sol_profile="phantom_bip44change", export_private=False ) vectors["bip39"].append({ "mnemonic": mnemonic, "passphrase": passphrase, "expected_seed_hex": seed_hex_p, "derived_addresses": {"phantom_bip44change": res_p["addresses"]} }) print("Derivation: Generated vectors for empty and non-empty passphrases.") # 3. Save out_path = Path(__file__).parent / "vectors.json" with open(out_path, "w", encoding="utf-8") as f: json.dump(vectors, f, indent=2) print(f"Success! Vectors written to {out_path}") if __name__ == "__main__": main()