"""Test that spec256k1 produces identical results to coincurve."""

import hashlib

import coincurve
import spec256k1

SECRETS = [
    b"\x01" * 32,
    b"\x02" * 32,
    b"\x0a" * 32,
    b"\x03" * 32,
    b"\x04" * 32,
]

MESSAGES = [hashlib.sha256(f"message {i}".encode()).digest() for i in range(10)]


def test_same_pubkey_from_secret():
    for secret in SECRETS:
        pk_cc = coincurve.PrivateKey(secret).public_key
        pk_sp = spec256k1.PrivateKey(secret).public_key
        assert pk_cc.format(compressed=False) == pk_sp.format(compressed=False)
        assert pk_cc.format(compressed=True) == pk_sp.format(compressed=True)


def test_coincurve_sign_spec256k1_recover():
    for secret in SECRETS:
        sk = coincurve.PrivateKey(secret)
        pk_cc = sk.public_key
        for msg in MESSAGES:
            sig = sk.sign_recoverable(msg, hasher=None)
            pk_sp = spec256k1.PublicKey.from_signature_and_message(sig, msg)
            assert pk_cc.format(compressed=False) == pk_sp.format(compressed=False)


def test_spec256k1_sign_coincurve_recover():
    for secret in SECRETS:
        sk = spec256k1.PrivateKey(secret)
        pk_sp = sk.public_key
        for msg in MESSAGES:
            sig = sk.sign_recoverable(msg)
            pk_cc = coincurve.PublicKey.from_signature_and_message(sig, msg, hasher=None)
            assert pk_sp.format(compressed=False) == pk_cc.format(compressed=False)


def test_pubkey_constructor_roundtrip():
    for secret in SECRETS:
        pk_cc = coincurve.PrivateKey(secret).public_key

        # compressed -> spec256k1 -> uncompressed matches
        pk_sp = spec256k1.PublicKey(pk_cc.format(compressed=True))
        assert pk_sp.format(compressed=False) == pk_cc.format(compressed=False)

        # uncompressed -> spec256k1 -> compressed matches
        pk_sp = spec256k1.PublicKey(pk_cc.format(compressed=False))
        assert pk_sp.format(compressed=True) == pk_cc.format(compressed=True)


def test_from_secret():
    for secret in SECRETS:
        pk_cc = coincurve.PrivateKey(secret).public_key
        pk_sp = spec256k1.PublicKey.from_secret(secret)
        assert pk_cc.format(compressed=False) == pk_sp.format(compressed=False)


def test_ethereum_execution_specs_pattern():
    """The exact call pattern used by ethereum/execution-specs."""
    sk = coincurve.PrivateKey(b"\x03" * 32)
    msg = hashlib.sha256(b"ethereum").digest()
    sig = sk.sign_recoverable(msg, hasher=None)

    pubkey = spec256k1.PublicKey.from_signature_and_message(sig, msg)
    raw = pubkey.format(compressed=False)[1:]  # 64-byte x||y

    raw_cc = (
        coincurve.PublicKey.from_signature_and_message(sig, msg, hasher=None)
        .format(compressed=False)[1:]
    )
    assert len(raw) == 64
    assert raw == raw_cc
