Skip to content

Conversation

@Komorebi-Z
Copy link
Contributor

@Komorebi-Z Komorebi-Z commented Jun 20, 2025

This Pull Request introduces several improvements and fixes to the pairing module.

Problem Background:

Upon further testing, I discovered that my previous attempt in #328 did not fully resolve the underlying issues. I've created a simple test script, test.py, that exposes several lingering problems:

from charm.toolbox.pairinggroup import PairingGroup, G1, G2, GT, ZR, pair, pc_element as Element

group = PairingGroup("MNT159")
print("********************** PairingGroup ZR Test **********************")
m = group.order()
print("m(Z):\t", m)

r1 = group.random(ZR)
print("r1(ZR):\t", r1)
print("0*ZR:\t", 0 * r1)
print("1*ZR:\t", 1 * r1)

r2 = group.random(ZR)
print("r2(ZR):\t", r2)
print("ZR^2:\t", r1 * r2)
print("Z*ZR:\t", int(r1) * r2)
print("ZR*Z:\t", r1 * int(r2))
print("Z^2mod:\t", int(r1) * int(r2) % m)

a = group.init(ZR, 1)
print("a(ZR):\t", a)
b = group.init(ZR, -1)
print("b(ZR):\t", b)
c = group.init(ZR, m + 123456789)
print("c(ZR):\t", c)
d = group.init(ZR, -m - 123456789)
print("d(ZR):\t", d)
r3 = group.init(ZR, int(r1 * m + r2))
print("r3(ZR):\t", r3)
print("r2 = r3:", r2 == r3)

print("*****************************************************************")

Key Contributions in this PR:

  1. Refined PyLongObject Size Handling & Macro Naming:

    • Problem: The PyLongObj_Size and Py_SET_SIZE macros, crucial for correctly getting/setting the signed length of the PyLongObject's ob_digit array, had incorrect logic, affecting Python 3.12+ environments. This can be demonstrated by b = group.init(ZR, -1) and m = group.order() respectively.
    • Solution: The logic for PyLongObj_Size and Py_SET_SIZE has been refined to better interpret the lv_tag field and extract the signed length. All related macros have been consistently renamed (e.g., PyLongObj_Sizel to PyLong_SIZE) for better readability.
    • NOTE: Everything seems normal now but MORE TESTS ARE NEEDED. Furthermore, the lv_tag field, which these macros interact with, appears to be an internal CPython design. Making reliance on its specific bit-level interpretation might be unstable (Python 3.14+ may introduce new C APIs per PEP 757).
  2. Fixed incorrect PyLong_SHIFT when compiled with MinGW for Windows 64-bit System:

    • Problem: On Windows 64-bit systems, when compiled with MinGW and run with Python 3.10 and below, the PyLong_SHIFT value was erroneously set to 15 bits, leading to incorrect longObjToMPZ behavior with very large integers. This can be demonstrated by c = group.init(ZR, m + 123456789) or d = group.init(ZR, -m - 123456789).
    • Solution: We defined the MS_WIN64 macro in the relevant header files, which sets SIZEOF_VOID_P to 8 in <your_python>/include/pyconfig.h, which further ensures PYLONG_BITS_IN_DIGIT is set to 30 in <your_python>/include/pyport.h, leading to the correct PyLong_SHIFT value.
  3. Enhanced Element_mul for Larger Integer Support:

    • Problem: In the Element_mul function, the variable z was limited to a signed long int type. This restricted its ability to process larger integer inputs, potentially causing overflows for certain operations. This can be demonstrated by print("Z*ZR:\t", int(r1) * r2) or print("ZR*Z:\t", r1 * int(r2)).
    • Solution: The type of z has been changed from signed long int to mpz_t. This allows the function to handle arbitrary-precision integers, expanding its capability to process much larger inputs without limitation.
  4. Optimized longObjToMPZ Performance:

    • The implementation of longObjToMPZ has been fine-tuned to eliminate redundant mpz related operations.

My apologies for the prior misunderstanding of the `lv_tag` field in the `_PyLongValue` structure.

**Note**: `lv_tag` is an internal CPython detail. Relying on such undocumented internals is unstable and may change (PEP 757).
This fix addresses the immediate issue but highlights this fragility.
This commit eliminates unnecessary initialization and copying overhead associated with the `temp` and `temp2` variables.
The function's efficiency is improved without altering its core functionality.
* Fixed the logic of `Py_SET_SIZE` macro in Python 3.12+
* Renamed macros to improve clarity.
* Replaced `signed long` with `mpz_t` for large integer support
* Introduced `debug_gmp()` macro to output GMP info
On Windows 64-bit with Python ≤ 3.10, pyconfig.h only sets `SIZEOF_VOID_P` to 8 when `MS_WIN64` is defined. Without this, pyport.h falls back to a 15-bit `PYLONG_BITS_IN_DIGIT`, resulting in an incorrect `PyLong_SHIFT` and bad big-integer conversions.
@jakinyele jakinyele self-requested a review June 20, 2025 17:10
Copy link
Member

@jakinyele jakinyele left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great!

@jakinyele jakinyele merged commit 14c6e8d into JHUISI:dev Jun 20, 2025
1 check passed
@Komorebi-Z Komorebi-Z deleted the fix-pairingmodule branch June 20, 2025 18:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants