Fix MSVC: portable 128-bit primitives in dgb_arith256.hpp (unblocks AUX_DOGE Windows) - #690
Merged
Conversation
MSVC has no __int128 keyword (C4235), so the AUX_DOGE=ON DGB+DOGE dual-parent Windows build failed in the DigiShield retarget arithmetic (mul_u64 / div_u64 / operator+=). Standalone DGB was green; only the dual-parent path pulls this header into an MSVC TU. Route the 64x64->128 multiply-add, 128/64 divide and 64+64 add through guarded detail:: helpers: unsigned __int128 on GCC/Clang, _umul128 / _udiv128 x64 intrinsics on MSVC. Both branches lower to the same mul/div/add-with-carry instructions, so the 256-bit truncation and every DigiShield boundary vector are bit-identical. Mirrors the mul128_shift portable precedent in dgb/share_tracker.hpp. Verified GCC AUX_DOGE=ON: digishield_walk_test 6/6, header_chain_test 35/35 (real Scrypt, oracle-pinned) green.
Add the consensus-arithmetic KAT integrator required to merge #690: assert the MSVC-portability rework of the DigiShield 256-bit retarget math is BIT-IDENTICAL across the native and portable branches, mirroring the bch #688 muldiv_kat precedent. The MSVC branch routes through the x64 _umul128/_udiv128 intrinsics that cannot be compiled or run on the Linux/macOS CI, so dgb_arith256.hpp now exposes a third, fully SOFTWARE oracle (detail::umul128_soft/udiv128_soft, the *_portable primitive twins, and u256_portable) using only 32-bit-limb arithmetic -- no __int128, no intrinsic. It is a genuinely independent computation; proving software == native across the DigiShield operand domain on Linux certifies the MSVC path we cannot run, since the x64 intrinsics are by ISA definition exactly the 64x64->128 product and 128/64 quotient the software reproduces. The oracle is header-only, compiled unconditionally, and NEVER referenced by the shipping u256 / mul_div_u256 -- the GCC/Clang retarget bytes stay byte-identical. arith256_muldiv_kat_test asserts mul_add_u128 / div_u128 / add_u128 and u256 mul_u64 / div_u64 / operator+= are bit-identical native-vs-portable across DigiShield target/scalar vectors + a 100k deterministic LCG fuzz, with dedicated stress of the _udiv128 hi<d running-remainder boundary (hi = d-1) so a precondition violation surfaces as a KAT fail, not field UB. Registered unconditionally in CMake and in BOTH build.yml --target allowlists (#143 NOT_BUILT trap). Pure header math: links only GTest. Local: 7/7 PASS; digishield_walk 6/6 + header_chain 35/35 unregressed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Blocker
AUX_DOGE=ON DGB+DOGE dual-parent build fails Windows x86_64 MSVC in
dgb_arith256.hpp— C4235__int128not supported. Standalone DGB build is green; only the dual-parent path pulls this header into an MSVC TU. Last live blocker on the v0.2.x wave.Fix
Route the three 128-bit ops in the DigiShield retarget arithmetic (
mul_u64/div_u64/operator+=) through guardeddetail::helpers:unsigned __int128(unchanged, in#else)_umul128/_udiv128x64 intrinsics (<intrin.h>)Both branches lower to the same mul/div/add-with-carry instructions, so the 256-bit truncation semantics and every DigiShield boundary vector are bit-identical. Mirrors the portable
mul128_shiftprecedent (8284845) already indgb/share_tracker.hpp.Only unguarded raw
__int128in the DGB tree was this file (header_chain.hpp hits are comments; share_tracker.hpp already guarded).Verification
GCC, AUX_DOGE=ON + COIN_DGB=ON:
digishield_walk_test6/6 PASSheader_chain_test35/35 PASS (real Scrypt PoW, oracle-pinned vectors)MSVC path can not be exercised on the Linux workstation — ci-steward #687 3-platform validation confirms non-hollow post-merge.
No self-merge — integrator reviews + merges.