Add C++ identity helper bindings

This commit is contained in:
John Poole 2026-05-17 12:49:55 -07:00
commit 7f0b302d00
5 changed files with 698 additions and 0 deletions

View file

@ -33,6 +33,17 @@ py::bytes string_to_py_bytes(const Bytes &value) {
return py::bytes(value);
}
std::string compute_identity_hash(py::object peer_identity_obj) {
const std::string identity_hex =
py::str(peer_identity_obj.attr("hex")()).cast<std::string>();
return identity_hex.substr(0, 16);
}
std::string get_fragmenter_key(py::object peer_identity_obj,
py::object /*peer_address*/) {
return py::str(peer_identity_obj.attr("hex")()).cast<std::string>();
}
struct Buffer {
std::map<uint16_t, Bytes> fragments;
uint16_t total = 0;
@ -444,6 +455,13 @@ public:
PYBIND11_MODULE(ble_protocol_core_cpp, m) {
m.doc() = "C++ protocol-core implementation for BLE Reticulum fragmentation";
m.def("compute_identity_hash", &compute_identity_hash,
py::arg("peer_identity"),
"Return the first 16 lowercase hex characters of a peer identity.");
m.def("get_fragmenter_key", &get_fragmenter_key, py::arg("peer_identity"),
py::arg("peer_address"),
"Return the full lowercase hex peer identity; peer_address is ignored.");
py::class_<BLEFragmenterCpp>(m, "BLEFragmenter")
.def(py::init<int>(), py::arg("mtu") = 185)
.def("fragment_packet", &BLEFragmenterCpp::fragment_packet,

View file

@ -0,0 +1,278 @@
============================================================
BLE Reticulum Migration Executive Summary
============================================================
1. Counts by phase/status/tag
phase status tag symbol_c
-------------- -------------- ---------- --------
0_inventory REVIEWED GLUE 39
0_inventory REVIEWED PLATFORM 33
0_inventory REVIEWED TEST 3
1_candidate REVIEWED CORE 2
1_protocol_cor FIELD_ACCEPTED CORE 14
e
2. Phase-1 C++ candidates
source_file class_name symbol_nam line_num tag status
-------------- -------------- ---------- -------- ------ ------------------------------------------------------------
src/ble_reticu BLEFragmen 52 CORE FIELD_ACCEPTED
lum/BLEFragmen ter
tation.py
src/ble_reticu BLEFragmenter __init__ 68 CORE FIELD_ACCEPTED
lum/BLEFragmen
tation.py
src/ble_reticu BLEFragmenter fragment_p 82 CORE FIELD_ACCEPTED
lum/BLEFragmen acket
tation.py
src/ble_reticu BLEFragmenter get_fragme 158 CORE FIELD_ACCEPTED
lum/BLEFragmen nt_overhea
tation.py d
src/ble_reticu BLEReassem 176 CORE FIELD_ACCEPTED
lum/BLEFragmen bler
tation.py
src/ble_reticu BLEReassembler __init__ 187 CORE FIELD_ACCEPTED
lum/BLEFragmen
tation.py
src/ble_reticu BLEReassembler receive_fr 205 CORE FIELD_ACCEPTED
lum/BLEFragmen agment
tation.py
src/ble_reticu BLEReassembler _reassembl 380 CORE FIELD_ACCEPTED
lum/BLEFragmen e
tation.py
src/ble_reticu BLEReassembler cleanup_st 402 CORE FIELD_ACCEPTED
lum/BLEFragmen ale_buffer
tation.py s
src/ble_reticu BLEReassembler get_statis 429 CORE FIELD_ACCEPTED
lum/BLEFragmen tics
tation.py
src/ble_reticu BLEReassembler reset_stat 443 CORE FIELD_ACCEPTED
lum/BLEFragmen istics
tation.py
src/ble_reticu HDLCFramer 450 CORE FIELD_ACCEPTED
lum/BLEFragmen
tation.py
src/ble_reticu HDLCFramer frame_pack 464 CORE FIELD_ACCEPTED
lum/BLEFragmen et
tation.py
src/ble_reticu HDLCFramer deframe_pa 491 CORE FIELD_ACCEPTED
lum/BLEFragmen cket
tation.py
src/ble_reticu BLEInterface _get_fragm 1858 CORE REVIEWED
lum/BLEInterfa enter_key
ce.py
src/ble_reticu BLEInterface _compute_i 1871 CORE REVIEWED
lum/BLEInterfa dentity_ha
ce.py sh
3. Symbols marked TESTED or ACCEPTED
source_file class_name symbol_nam phase status notes_preview
-------------- -------------- ---------- -------- ------ ------------------------------------------------------------
src/ble_reticu BLEFragmen 1_protoc FIELD_ Imported from Codex_response_20260616_1514.md; original symb
lum/BLEFragmen ter ol_core ACCEPT ol cell: BLEFragment
tation.py ED
src/ble_reticu BLEFragmenter __init__ 1_protoc FIELD_ Imported from Codex_response_20260616_1514.md; original symb
lum/BLEFragmen ol_core ACCEPT ol cell: BLEFragment
tation.py ED
src/ble_reticu BLEFragmenter fragment_p 1_protoc FIELD_ Imported from Codex_response_20260616_1514.md; original symb
lum/BLEFragmen acket ol_core ACCEPT ol cell: BLEFragment
tation.py ED
src/ble_reticu BLEFragmenter get_fragme 1_protoc FIELD_ Imported from Codex_response_20260616_1514.md; original symb
lum/BLEFragmen nt_overhea ol_core ACCEPT ol cell: BLEFragment
tation.py d ED
src/ble_reticu BLEReassem 1_protoc FIELD_ Imported from Codex_response_20260616_1514.md; original symb
lum/BLEFragmen bler ol_core ACCEPT ol cell: BLEReassemb
tation.py ED
src/ble_reticu BLEReassembler __init__ 1_protoc FIELD_ Imported from Codex_response_20260616_1514.md; original symb
lum/BLEFragmen ol_core ACCEPT ol cell: BLEReassemb
tation.py ED
src/ble_reticu BLEReassembler receive_fr 1_protoc FIELD_ Imported from Codex_response_20260616_1514.md; original symb
lum/BLEFragmen agment ol_core ACCEPT ol cell: BLEReassemb
tation.py ED
src/ble_reticu BLEReassembler _reassembl 1_protoc FIELD_ Imported from Codex_response_20260616_1514.md; original symb
lum/BLEFragmen e ol_core ACCEPT ol cell: BLEReassemb
tation.py ED
src/ble_reticu BLEReassembler cleanup_st 1_protoc FIELD_ Imported from Codex_response_20260616_1514.md; original symb
lum/BLEFragmen ale_buffer ol_core ACCEPT ol cell: BLEReassemb
tation.py s ED
src/ble_reticu BLEReassembler get_statis 1_protoc FIELD_ Imported from Codex_response_20260616_1514.md; original symb
lum/BLEFragmen tics ol_core ACCEPT ol cell: BLEReassemb
tation.py ED
src/ble_reticu BLEReassembler reset_stat 1_protoc FIELD_ Imported from Codex_response_20260616_1514.md; original symb
lum/BLEFragmen istics ol_core ACCEPT ol cell: BLEReassemb
tation.py ED
src/ble_reticu HDLCFramer 1_protoc FIELD_ Imported from Codex_response_20260616_1514.md; original symb
lum/BLEFragmen ol_core ACCEPT ol cell: HDLCFramer
tation.py ED
src/ble_reticu HDLCFramer frame_pack 1_protoc FIELD_ Imported from Codex_response_20260616_1514.md; original symb
lum/BLEFragmen et ol_core ACCEPT ol cell: HDLCFramer.
tation.py ED
src/ble_reticu HDLCFramer deframe_pa 1_protoc FIELD_ Imported from Codex_response_20260616_1514.md; original symb
lum/BLEFragmen cket ol_core ACCEPT ol cell: HDLCFramer.
tation.py ED
4. Remaining CORE symbols not accepted
source_file class_name symbol_nam line_num phase status rationale_preview
-------------- -------------- ---------- -------- ------ ------------------------------------------------------------ -------------------------------------------------------
src/ble_reticu BLEInterface _get_fragm 1858 1_cand REVIEWED Pure identity-to-fragment-state key; cleanly separable.
lum/BLEInterfa enter_key idate
ce.py
src/ble_reticu BLEInterface _compute_i 1871 1_cand REVIEWED Pure identity truncation rule; cleanly separable.
lum/BLEInterfa dentity_ha idate
ce.py sh
5. Unknown or needs-review symbols
6. Do-not-port-yet inventory
tag symbol_count
-------------- --------------
GLUE 39
PLATFORM 33
TEST 3
7. Candidate next tasks
source_file class_name symbol_nam line_num tag phase status cpp_candidate rationale_preview
-------------- -------------- ---------- -------- ------ ------------------------------------------------------------ -------- ------------- -------------------------------------------------------
src/ble_reticu BLEInterface _get_fragm 1858 CORE 1_candidate REVIEWED 1 Pure identity-to-fragment-state key; cleanly separable.
lum/BLEInterfa enter_key
ce.py
src/ble_reticu BLEInterface _compute_i 1871 CORE 1_candidate REVIEWED 1 Pure identity truncation rule; cleanly separable.
lum/BLEInterfa dentity_ha
ce.py sh
8. Latest review notes
reviewed_at reviewer source_fil class_na symbol old_status new_status note_preview
-------------- -------------- ---------- -------- ------ ------------------------------------------------------------ -------------- ------------------------------------------------------------
2026-05-17 19: jlpoole + Code src/ble_re BLEFra FIELD_ACCEPTED FIELD_ACCEPTED 2026-05-17: C++ fragmentation/reassembly/HDLC backend accept
27:31 x + ChatGPT ticulum/BL gmente ed after live bilateral Constitution tra
EFragmenta r
tion.py
2026-05-17 19: jlpoole + Code src/ble_re BLERea FIELD_ACCEPTED FIELD_ACCEPTED 2026-05-17: C++ fragmentation/reassembly/HDLC backend accept
27:31 x + ChatGPT ticulum/BL ssembl ed after live bilateral Constitution tra
EFragmenta er
tion.py
2026-05-17 19: jlpoole + Code src/ble_re HDLCFr FIELD_ACCEPTED FIELD_ACCEPTED 2026-05-17: C++ fragmentation/reassembly/HDLC backend accept
27:31 x + ChatGPT ticulum/BL amer ed after live bilateral Constitution tra
EFragmenta
tion.py
2026-05-17 19: jlpoole + Code src/ble_re BLEFragm __init FIELD_ACCEPTED FIELD_ACCEPTED 2026-05-17: C++ fragmentation/reassembly/HDLC backend accept
27:31 x + ChatGPT ticulum/BL enter __ ed after live bilateral Constitution tra
EFragmenta
tion.py
2026-05-17 19: jlpoole + Code src/ble_re BLEFragm fragme FIELD_ACCEPTED FIELD_ACCEPTED 2026-05-17: C++ fragmentation/reassembly/HDLC backend accept
27:31 x + ChatGPT ticulum/BL enter nt_pac ed after live bilateral Constitution tra
EFragmenta ket
tion.py
2026-05-17 19: jlpoole + Code src/ble_re BLEFragm get_fr FIELD_ACCEPTED FIELD_ACCEPTED 2026-05-17: C++ fragmentation/reassembly/HDLC backend accept
27:31 x + ChatGPT ticulum/BL enter agment ed after live bilateral Constitution tra
EFragmenta _overh
tion.py ead
2026-05-17 19: jlpoole + Code src/ble_re BLEReass __init FIELD_ACCEPTED FIELD_ACCEPTED 2026-05-17: C++ fragmentation/reassembly/HDLC backend accept
27:31 x + ChatGPT ticulum/BL embler __ ed after live bilateral Constitution tra
EFragmenta
tion.py
2026-05-17 19: jlpoole + Code src/ble_re BLEReass _reass FIELD_ACCEPTED FIELD_ACCEPTED 2026-05-17: C++ fragmentation/reassembly/HDLC backend accept
27:31 x + ChatGPT ticulum/BL embler emble ed after live bilateral Constitution tra
EFragmenta
tion.py
2026-05-17 19: jlpoole + Code src/ble_re BLEReass cleanu FIELD_ACCEPTED FIELD_ACCEPTED 2026-05-17: C++ fragmentation/reassembly/HDLC backend accept
27:31 x + ChatGPT ticulum/BL embler p_stal ed after live bilateral Constitution tra
EFragmenta e_buff
tion.py ers
2026-05-17 19: jlpoole + Code src/ble_re BLEReass get_st FIELD_ACCEPTED FIELD_ACCEPTED 2026-05-17: C++ fragmentation/reassembly/HDLC backend accept
27:31 x + ChatGPT ticulum/BL embler atisti ed after live bilateral Constitution tra
EFragmenta cs
tion.py
2026-05-17 19: jlpoole + Code src/ble_re BLEReass receiv FIELD_ACCEPTED FIELD_ACCEPTED 2026-05-17: C++ fragmentation/reassembly/HDLC backend accept
27:31 x + ChatGPT ticulum/BL embler e_frag ed after live bilateral Constitution tra
EFragmenta ment
tion.py
2026-05-17 19: jlpoole + Code src/ble_re BLEReass reset_ FIELD_ACCEPTED FIELD_ACCEPTED 2026-05-17: C++ fragmentation/reassembly/HDLC backend accept
27:31 x + ChatGPT ticulum/BL embler statis ed after live bilateral Constitution tra
EFragmenta tics
tion.py
2026-05-17 19: jlpoole + Code src/ble_re HDLCFram defram FIELD_ACCEPTED FIELD_ACCEPTED 2026-05-17: C++ fragmentation/reassembly/HDLC backend accept
27:31 x + ChatGPT ticulum/BL er e_pack ed after live bilateral Constitution tra
EFragmenta et
tion.py
2026-05-17 19: jlpoole + Code src/ble_re HDLCFram frame_ FIELD_ACCEPTED FIELD_ACCEPTED 2026-05-17: C++ fragmentation/reassembly/HDLC backend accept
27:31 x + ChatGPT ticulum/BL er packet ed after live bilateral Constitution tra
EFragmenta
tion.py
2026-05-16 22: codex src/ble_re BLEFra REVIEWED Imported from Codex Markdown review. Rationale: Pure BLE pac
50:00 ticulum/BL gmente ket fragmentation format; RNS only loggi
EFragmenta r
tion.py
2026-05-16 22: codex src/ble_re BLEFragm __init REVIEWED Imported from Codex Markdown review. Rationale: MTU/header s
50:00 ticulum/BL enter __ izing logic.
EFragmenta
tion.py
2026-05-16 22: codex src/ble_re BLEFragm fragme REVIEWED Imported from Codex Markdown review. Rationale: Core packet-
50:00 ticulum/BL enter nt_pac to-fragments encoding.
EFragmenta ket
tion.py
2026-05-16 22: codex src/ble_re BLEFragm get_fr REVIEWED Imported from Codex Markdown review. Rationale: Pure sizing/
50:00 ticulum/BL enter agment overhead calculation.
EFragmenta _overh
tion.py ead
2026-05-16 22: codex src/ble_re BLERea REVIEWED Imported from Codex Markdown review. Rationale: Core fragmen
50:00 ticulum/BL ssembl t state machine; RNS only logging.
EFragmenta er
tion.py
2026-05-16 22: codex src/ble_re BLEReass __init REVIEWED Imported from Codex Markdown review. Rationale: Protocol rea
50:00 ticulum/BL embler __ ssembly state.
EFragmenta
tion.py

View file

@ -0,0 +1,145 @@
--
-- For ChatGPT's tracking
--
-- 20260517 ChatGPT
-- $Header$
--
-- Example:
-- cd /usr/local/src/ble-reticulum/migration
-- sqlite3 ble_migration.sqlite ".read sql/executive_summary.sql"
--
-- Purpose:
-- Executive summary of BLE Reticulum C++ migration status.
.headers on
.mode column
.width 14 14 10 8 6 60
.print ''
.print '============================================================'
.print 'BLE Reticulum Migration Executive Summary'
.print '============================================================'
.print ''
.print '1. Counts by phase/status/tag'
SELECT
phase,
status,
tag,
COUNT(*) AS symbol_count
FROM symbols
GROUP BY phase, status, tag
ORDER BY phase, status, tag;
.print ''
.print '2. Phase-1 C++ candidates'
SELECT
source_file,
COALESCE(class_name, '') AS class_name,
symbol_name,
line_number,
tag,
status
FROM symbols
WHERE phase = '1_protocol_core'
OR cpp_candidate = 1
ORDER BY source_file, line_number;
.print ''
.print '3. Symbols marked TESTED or ACCEPTED'
SELECT
source_file,
COALESCE(class_name, '') AS class_name,
symbol_name,
phase,
status,
substr(COALESCE(notes, ''), 1, 80) AS notes_preview
FROM symbols
WHERE status IN ('TESTED', 'ACCEPTED', 'FIELD_ACCEPTED', 'WRAPPED_FOR_PYTHON')
ORDER BY source_file, line_number;
.print ''
.print '4. Remaining CORE symbols not accepted'
SELECT
source_file,
COALESCE(class_name, '') AS class_name,
symbol_name,
line_number,
phase,
status,
substr(COALESCE(rationale, ''), 1, 80) AS rationale_preview
FROM symbols
WHERE tag = 'CORE'
AND status NOT IN ('ACCEPTED', 'FIELD_ACCEPTED', 'REJECTED', 'DEFERRED')
ORDER BY source_file, line_number;
.print ''
.print '5. Unknown or needs-review symbols'
SELECT
source_file,
COALESCE(class_name, '') AS class_name,
symbol_name,
line_number,
tag,
status,
substr(COALESCE(rationale, ''), 1, 80) AS rationale_preview
FROM symbols
WHERE tag = 'UNKNOWN'
OR status = 'NEEDS_REVIEW'
ORDER BY source_file, line_number;
.print ''
.print '6. Do-not-port-yet inventory'
SELECT
tag,
COUNT(*) AS symbol_count
FROM symbols
WHERE tag IN ('GLUE', 'PLATFORM', 'TEST')
GROUP BY tag
ORDER BY tag;
.print ''
.print '7. Candidate next tasks'
SELECT
source_file,
COALESCE(class_name, '') AS class_name,
symbol_name,
line_number,
tag,
phase,
status,
cpp_candidate,
substr(COALESCE(rationale, ''), 1, 100) AS rationale_preview
FROM symbols
WHERE (
tag = 'CORE'
AND status IN ('DISCOVERED', 'CLASSIFIED', 'TESTED', 'WRAPPED_FOR_PYTHON')
)
OR (
cpp_candidate = 1
AND status NOT IN ('ACCEPTED', 'FIELD_ACCEPTED', 'REJECTED', 'DEFERRED')
)
ORDER BY
CASE
WHEN source_file LIKE '%BLEInterface.py%' THEN 1
WHEN source_file LIKE '%BLEFragmentation.py%' THEN 2
ELSE 3
END,
source_file,
line_number;
.print ''
.print '8. Latest review notes'
SELECT
r.reviewed_at,
r.reviewer,
s.source_file,
COALESCE(s.class_name, '') AS class_name,
s.symbol_name,
r.old_status,
r.new_status,
substr(COALESCE(r.note, ''), 1, 100) AS note_preview
FROM reviews r
JOIN symbols s ON s.symbol_id = r.symbol_id
ORDER BY r.reviewed_at DESC
LIMIT 20;

View file

@ -0,0 +1,78 @@
-- 20260517 ChatGPT
-- $Header$
--
-- Example:
-- cd /usr/local/src/ble-reticulum/migration
-- sqlite3 ble_migration.sqlite ".read sql/mark_fragmentation_cpp_field_accepted_20260517.sql"
--
-- Purpose:
-- Mark Phase 1 C++ fragmentation/reassembly/HDLC work as field accepted
-- after successful bilateral Constitution transfer using the C++ backend.
BEGIN;
UPDATE symbols
SET status = 'FIELD_ACCEPTED',
phase = '1_protocol_core',
notes = trim(COALESCE(notes, '') || char(10) ||
'2026-05-17: FIELD_ACCEPTED. C++ protocol-core backend passed live bilateral Constitution transfer after rebooting devzero1 and increasing transfer timeout from 60 to 90 seconds. A forensic run directory was preserved for the pre-reboot hardware/timeout lock investigation.'),
updated_at = CURRENT_TIMESTAMP
WHERE source_file = 'src/ble_reticulum/BLEFragmentation.py'
AND (
symbol_name IN (
'BLEFragmenter',
'__init__',
'fragment_packet',
'get_fragment_overhead',
'BLEReassembler',
'receive_fragment',
'_reassemble',
'cleanup_stale_buffers',
'get_statistics',
'reset_statistics',
'HDLCFramer',
'frame_packet',
'deframe_packet'
)
OR class_name IN ('BLEFragmenter', 'BLEReassembler', 'HDLCFramer')
);
INSERT INTO reviews (
symbol_id,
reviewer,
old_tag,
new_tag,
old_status,
new_status,
note
)
SELECT
symbol_id,
'jlpoole + Codex + ChatGPT',
tag,
tag,
status,
'FIELD_ACCEPTED',
'2026-05-17: C++ fragmentation/reassembly/HDLC backend accepted after live bilateral Constitution transfer. Reboot of devzero1 cleared suspected BLE/hardware lock after earlier 60-second timeout runs. Timeout increased to 90 seconds. Forensic run directory preserved.'
FROM symbols
WHERE source_file = 'src/ble_reticulum/BLEFragmentation.py'
AND (
symbol_name IN (
'BLEFragmenter',
'__init__',
'fragment_packet',
'get_fragment_overhead',
'BLEReassembler',
'receive_fragment',
'_reassemble',
'cleanup_stale_buffers',
'get_statistics',
'reset_statistics',
'HDLCFramer',
'frame_packet',
'deframe_packet'
)
OR class_name IN ('BLEFragmenter', 'BLEReassembler', 'HDLCFramer')
);
COMMIT;

View file

@ -0,0 +1,179 @@
import os
import sys
import pytest
REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
SRC_DIR = os.path.join(REPO_ROOT, "src")
CPP_BUILD_DIR = os.path.join(REPO_ROOT, "migration", "protocol_core")
sys.path.insert(0, SRC_DIR)
sys.path.insert(0, CPP_BUILD_DIR)
cpp = pytest.importorskip(
"ble_protocol_core_cpp",
reason=(
"compiled pybind11 module missing; build with "
"`python3 migration/protocol_core/setup.py build_ext --inplace`"
),
)
try:
from ble_reticulum.BLEInterface import BLEInterface
except Exception:
BLEInterface = None
REFERENCE_MODE = "real_bleinterface" if BLEInterface is not None else "source_fallback"
def python_interface():
if BLEInterface is None:
return None
return object.__new__(BLEInterface)
def py_compute_identity_hash(peer_identity):
if BLEInterface is None:
return peer_identity.hex()[:16]
return BLEInterface._compute_identity_hash(python_interface(), peer_identity)
def py_get_fragmenter_key(peer_identity, peer_address):
if BLEInterface is None:
return peer_identity.hex()
return BLEInterface._get_fragmenter_key(
python_interface(), peer_identity, peer_address
)
def test_reference_mode_is_explicit():
assert REFERENCE_MODE in {"real_bleinterface", "source_fallback"}
def test_real_bleinterface_reference_when_importable():
if BLEInterface is None:
pytest.skip("BLEInterface dependencies are not importable; using source fallback")
assert REFERENCE_MODE == "real_bleinterface"
assert python_interface() is not None
def test_source_fallback_matches_current_helper_logic_when_bleinterface_unavailable():
if BLEInterface is not None:
pytest.skip("BLEInterface importable; source fallback not used")
assert REFERENCE_MODE == "source_fallback"
interface_path = os.path.join(SRC_DIR, "ble_reticulum", "BLEInterface.py")
with open(interface_path, "r", encoding="utf-8") as handle:
source = handle.read()
assert "return peer_identity.hex()" in source
assert "return peer_identity.hex()[:16]" in source
def assert_same_exception(py_callable, cpp_callable):
with pytest.raises(Exception) as py_exc:
py_callable()
with pytest.raises(Exception) as cpp_exc:
cpp_callable()
assert type(cpp_exc.value) is type(py_exc.value)
@pytest.mark.parametrize(
"identity",
[
bytes.fromhex("00112233445566778899aabbccddeeff"),
b"\x00" * 16,
b"\xff" * 16,
bytes(range(16)),
],
)
def test_normal_16_byte_identities(identity):
assert cpp.compute_identity_hash(identity) == py_compute_identity_hash(identity)
assert cpp.get_fragmenter_key(identity, "AA:BB:CC:DD:EE:FF") == py_get_fragmenter_key(
identity, "AA:BB:CC:DD:EE:FF"
)
@pytest.mark.parametrize("identity", [b"", b"\x01", b"\x01\x23\x45\x67\x89\xab\xcd"])
def test_shorter_identities(identity):
assert cpp.compute_identity_hash(identity) == py_compute_identity_hash(identity)
assert cpp.get_fragmenter_key(identity, None) == py_get_fragmenter_key(identity, None)
@pytest.mark.parametrize(
"identity",
[
bytes(range(17)),
bytes(range(32)),
b"\x10\x20\x30\x40\x50\x60\x70\x80" + b"\x99" * 64,
],
)
def test_longer_identities(identity):
assert cpp.compute_identity_hash(identity) == py_compute_identity_hash(identity)
assert cpp.get_fragmenter_key(identity, "") == py_get_fragmenter_key(identity, "")
@pytest.mark.parametrize("identity", [None, "00112233", 1234, object()])
def test_none_or_invalid_identity_values(identity):
assert_same_exception(
lambda: py_compute_identity_hash(identity),
lambda: cpp.compute_identity_hash(identity),
)
assert_same_exception(
lambda: py_get_fragmenter_key(identity, "AA:BB"),
lambda: cpp.get_fragmenter_key(identity, "AA:BB"),
)
def test_peer_address_ignored_for_fragmenter_key():
identity = bytes.fromhex("00112233445566778899aabbccddeeff")
addresses = [
None,
"",
"AA:BB:CC:DD:EE:FF",
"11:22:33:44:55:66",
object(),
]
expected = py_get_fragmenter_key(identity, addresses[0])
for address in addresses:
assert py_get_fragmenter_key(identity, address) == expected
assert cpp.get_fragmenter_key(identity, address) == expected
def test_stable_lowercase_hex_formatting():
identity = bytes.fromhex("ABCDEF0123456789ABCDEF0123456789")
assert py_compute_identity_hash(identity) == "abcdef0123456789"
assert cpp.compute_identity_hash(identity) == "abcdef0123456789"
assert py_get_fragmenter_key(identity, "ignored") == identity.hex()
assert cpp.get_fragmenter_key(identity, "ignored") == identity.hex()
assert cpp.compute_identity_hash(identity).islower()
assert cpp.get_fragmenter_key(identity, "ignored").islower()
def test_collision_sensitive_truncated_hash_edge_case():
shared_prefix = bytes.fromhex("0011223344556677")
identity_a = shared_prefix + bytes.fromhex("0000000000000000")
identity_b = shared_prefix + bytes.fromhex("ffffffffffffffff")
assert py_compute_identity_hash(identity_a) == py_compute_identity_hash(identity_b)
assert cpp.compute_identity_hash(identity_a) == cpp.compute_identity_hash(identity_b)
assert py_get_fragmenter_key(identity_a, "addr1") != py_get_fragmenter_key(
identity_b, "addr2"
)
assert cpp.get_fragmenter_key(identity_a, "addr1") != cpp.get_fragmenter_key(
identity_b, "addr2"
)
def test_bytearray_matches_current_python_hex_behavior():
identity = bytearray(bytes.fromhex("00112233445566778899aabbccddeeff"))
assert cpp.compute_identity_hash(identity) == py_compute_identity_hash(identity)
assert cpp.get_fragmenter_key(identity, "ignored") == py_get_fragmenter_key(
identity, "ignored"
)