From f4bd7361bbd374acbbf0ec97c7a67931886a79d5 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 6 Feb 2026 18:38:49 -0800 Subject: [PATCH 01/78] Windows asm/ABI and runtime fixes --- src/asm_avx512_ifma.h | 8 +-- src/asm_base.h | 16 +++--- src/asm_gcd_128.h | 6 +-- src/asm_gcd_base_continued_fractions.h | 4 +- src/asm_gcd_base_divide_table.h | 4 +- src/asm_gcd_unsigned.h | 4 +- src/asm_types.h | 16 ++++++ src/asm_vm.h | 58 +++++++++++++++++++++ src/avx512_integer.h | 2 +- src/avx512_test.cpp | 2 +- src/callback.h | 2 +- src/generic.h | 6 +-- src/include.h | 5 ++ src/parameters.h | 71 +++++++++++++++++++++----- src/prover_base.hpp | 2 +- src/prover_test.cpp | 2 +- src/threading.h | 2 + src/uint128_t/uint128_t.cpp | 5 +- src/vdf.h | 10 ++-- src/vdf_bench.cpp | 5 +- src/vdf_test.cpp | 4 +- 21 files changed, 188 insertions(+), 46 deletions(-) diff --git a/src/asm_avx512_ifma.h b/src/asm_avx512_ifma.h index 567e762b..8041b257 100644 --- a/src/asm_avx512_ifma.h +++ b/src/asm_avx512_ifma.h @@ -593,11 +593,13 @@ void add(reg_alloc regs, avx512_integer in_a, avx512_integer in_b, avx512_intege static bool outputted_table=false; if (!outputted_table) { - #ifdef CHIAOSX +#ifdef CHIA_WINDOWS + APPEND_M(str( ".section .rdata,\"dr\"" )); +#elif defined(CHIAOSX) APPEND_M(str( ".text " )); - #else +#else APPEND_M(str( ".text 1" )); - #endif +#endif string neg_1=to_hex(~uint64(0)); diff --git a/src/asm_base.h b/src/asm_base.h index 14673904..80e42720 100644 --- a/src/asm_base.h +++ b/src/asm_base.h @@ -53,7 +53,9 @@ string track_asm(string comment, string jump_to = "") { } string comment_label=m.alloc_label(); -#ifdef CHIAOSX +#if defined(CHIA_WINDOWS) + APPEND_M(str( ".section .rdata,\"dr\"" )); +#elif defined(CHIAOSX) APPEND_M(str( ".text " )); #else APPEND_M(str( ".text 1" )); @@ -81,7 +83,7 @@ string track_asm(string comment, string jump_to = "") { APPEND_M(str( "MOV RAX, [asm_tracking_data+#]", to_hex(8*(id-1)) )); APPEND_M(str( "LEA RAX, [RAX+1]" )); APPEND_M(str( "MOV [asm_tracking_data+#], RAX", to_hex(8*(id-1)) )); -#ifdef CHIAOSX +#if defined(CHIAOSX) || defined(CHIA_WINDOWS) APPEND_M(str( "LEA RAX, [RIP+comment_label] " )); #else APPEND_M(str( "MOV RAX, OFFSET FLAT:#", comment_label )); @@ -105,7 +107,9 @@ string constant_address_uint64(uint64 value_bits_0, uint64 value_bits_1, bool us if (name.empty()) { name=m.alloc_label(); -#ifdef CHIAOSX +#if defined(CHIA_WINDOWS) + APPEND_M(str( ".section .rdata,\"dr\"" )); +#elif defined(CHIAOSX) APPEND_M(str( ".text " )); #else APPEND_M(str( ".text 1" )); @@ -116,7 +120,7 @@ string constant_address_uint64(uint64 value_bits_0, uint64 value_bits_1, bool us APPEND_M(str( ".quad #", to_hex(value_bits_1) )); //lane 1 APPEND_M(str( ".text" )); } -#ifdef CHIAOSX +#if defined(CHIAOSX) || defined(CHIA_WINDOWS) return (use_brackets)? str( "[RIP+#]", name ) : name; #else return (use_brackets)? str( "[#]", name ) : name; @@ -136,7 +140,7 @@ string constant_address_avx512_uint64(array value, bool use_brackets= if (name.empty()) { name=m.alloc_label(); -#ifdef CHIAOSX +#if defined(CHIAOSX) || defined(CHIA_WINDOWS) APPEND_M(str( ".text " )); #else APPEND_M(str( ".text 1" )); @@ -148,7 +152,7 @@ string constant_address_avx512_uint64(array value, bool use_brackets= } APPEND_M(str( ".text" )); } -#ifdef CHIAOSX +#if defined(CHIAOSX) || defined(CHIA_WINDOWS) return (use_brackets)? str( "ZMMWORD PTR [RIP+#]", name ) : name; #else return (use_brackets)? str( "ZMMWORD PTR [#]", name ) : name; diff --git a/src/asm_gcd_128.h b/src/asm_gcd_128.h index b127f56b..2ce0a3b9 100644 --- a/src/asm_gcd_128.h +++ b/src/asm_gcd_128.h @@ -511,7 +511,7 @@ void gcd_128( APPEND_M(str( "MOV `tmp_0, `ab_0_1" )); APPEND_M(str( "MOV `tmp_1, 64" )); APPEND_M(str( "CMP `ab_0_1, 0" )); -#ifdef CHIAOSX +#if defined(CHIAOSX) || defined(CHIA_WINDOWS) string cmoveq_label1=m.alloc_label(); APPEND_M(str( "JNE #", cmoveq_label1)); APPEND_M(str( "MOV `tmp_0, `ab_0_0" )); @@ -568,7 +568,7 @@ void gcd_128( //vector_is_lehmer=((spill_is_lehmer | shift_amount)!=0)? <~0, ~0> : <0, 0> APPEND_M(str( "OR `tmp_2, `tmp_1" )); if (!use_divide_table) { -#ifdef CHIAOSX +#if defined(CHIAOSX) || defined(CHIA_WINDOWS) APPEND_M(str( "LEA `tmp_3, [RIP+#]", constant_address_uint64(0ull, 0ull, false) )); APPEND_M(str( "LEA `tmp_0, [RIP+#]", constant_address_uint64(~(0ull), ~(0ull), false) )); #else @@ -576,7 +576,7 @@ void gcd_128( APPEND_M(str( "MOV `tmp_0, OFFSET FLAT:#", constant_address_uint64(~(0ull), ~(0ull), false) )); #endif } else { -#ifdef CHIAOSX +#if defined(CHIAOSX) || defined(CHIA_WINDOWS) APPEND_M(str( "LEA `tmp_3, [RIP+#]", constant_address_uint64(gcd_mask_exact[0], gcd_mask_exact[1], false) )); APPEND_M(str( "LEA `tmp_0, [RIP+#]", constant_address_uint64(gcd_mask_approximate[0], gcd_mask_approximate[1], false) )); #else diff --git a/src/asm_gcd_base_continued_fractions.h b/src/asm_gcd_base_continued_fractions.h index a1e25fde..935bb2c3 100644 --- a/src/asm_gcd_base_continued_fractions.h +++ b/src/asm_gcd_base_continued_fractions.h @@ -78,7 +78,9 @@ void gcd_base_continued_fraction( static bool outputted_table=false; if (!outputted_table) { -#ifdef CHIAOSX +#ifdef CHIA_WINDOWS + APPEND_M(str( ".section .rdata,\"dr\"" )); +#elif defined(CHIAOSX) APPEND_M(str( ".text " )); #else APPEND_M(str( ".text 1" )); diff --git a/src/asm_gcd_base_divide_table.h b/src/asm_gcd_base_divide_table.h index de3d2fc4..57ccfaf8 100644 --- a/src/asm_gcd_base_divide_table.h +++ b/src/asm_gcd_base_divide_table.h @@ -16,7 +16,9 @@ void divide_table(reg_alloc regs, reg_scalar a, reg_scalar b, reg_scalar q, reg_ static bool outputted_table=false; if (!outputted_table) { -#ifdef CHIAOSX +#ifdef CHIA_WINDOWS + APPEND_M(str( ".section .rdata,\"dr\"" )); +#elif defined(CHIAOSX) APPEND_M(str( ".text " )); #else APPEND_M(str( ".text 1" )); diff --git a/src/asm_gcd_unsigned.h b/src/asm_gcd_unsigned.h index fd2ab968..63979e7e 100644 --- a/src/asm_gcd_unsigned.h +++ b/src/asm_gcd_unsigned.h @@ -442,7 +442,9 @@ void gcd_unsigned( string jump_table_label=m.alloc_label(); -#ifdef CHIAOSX +#ifdef CHIA_WINDOWS + APPEND_M(str( ".section .rdata,\"dr\"" )); +#elif defined(CHIAOSX) APPEND_M(str( ".text " )); #else APPEND_M(str( ".text 1" )); diff --git a/src/asm_types.h b/src/asm_types.h index 6a50b2ca..1de1156e 100644 --- a/src/asm_types.h +++ b/src/asm_types.h @@ -460,12 +460,20 @@ struct reg_spill { reg_spill(int t_value, int t_size, int t_alignment) : value(t_value), size(t_size), alignment(t_alignment) {} int get_rsp_offset() const { +#ifdef CHIA_WINDOWS + return value + 8; +#else return value-spill_bytes; +#endif } //this is negative uint64 get_rsp_offset_uint64() const { +#ifdef CHIA_WINDOWS + return uint64(value + 8); +#else return uint64(value-spill_bytes); +#endif } string name() const { @@ -473,13 +481,21 @@ struct reg_spill { assert(value%alignment==0); assert(value+size<=spill_bytes); +#ifdef CHIA_WINDOWS + return str( "[RSP+#]", to_hex(value + 8) ); +#else return str( "[RSP+#]", to_hex(value-spill_bytes) ); +#endif } typedef void bindable; void bind_impl(expand_macros& m, string n) const { m.bind_impl(n, name()); +#ifdef CHIA_WINDOWS + m.bind_impl(n + "_rsp_offset", to_hex(value + 8)); +#else m.bind_impl(n + "_rsp_offset", to_hex(value-spill_bytes)); +#endif } reg_spill operator+(int byte_offset) const { diff --git a/src/asm_vm.h b/src/asm_vm.h index a73bc88e..b3bad099 100644 --- a/src/asm_vm.h +++ b/src/asm_vm.h @@ -40,8 +40,16 @@ struct asm_function { vector args; vector pop_regs; +#ifdef CHIA_WINDOWS + const vector all_save_regs={reg_rbp, reg_rbx, reg_rsi, reg_rdi, reg_r12, reg_r13, reg_r14, reg_r15}; +#else const vector all_save_regs={reg_rbp, reg_rbx, reg_r12, reg_r13, reg_r14, reg_r15}; +#endif +#ifdef CHIA_WINDOWS + const vector all_arg_regs={reg_rcx, reg_rdx, reg_r8, reg_r9, reg_r10, reg_r11}; +#else const vector all_arg_regs={reg_rdi, reg_rsi, reg_rdx, reg_rcx, reg_r8, reg_r9}; +#endif const reg_scalar return_reg=reg_rax; bool d_align_stack=true; @@ -83,6 +91,15 @@ struct asm_function { regs.get_scalar(r); args.push_back(r); } +#ifdef CHIA_WINDOWS + // Load 5th+ args from the stack (Windows x64 calling convention). + if (num_args > 4) { + APPEND_M(str( "MOV R10, [RSP+0x28]" )); + } + if (num_args > 5) { + APPEND_M(str( "MOV R11, [RSP+0x30]" )); + } +#endif //takes 6 cycles max if nothing else to do int num_available_regs=15-all_save_regs.size(); @@ -98,6 +115,31 @@ struct asm_function { assert(num_available_regs==num_regs); if (align_stack) { +#ifdef CHIA_WINDOWS + // Windows x64: reserve spill area + shadow space + xmm save area + align to 64. + const int windows_saved_rsp_bytes = 8; + const int windows_shadow_space_bytes = 0x20; + const int windows_xmm_save_bytes = 10 * 32; // YMM6-15 + const int windows_frame_bytes = + windows_saved_rsp_bytes + spill_bytes + windows_shadow_space_bytes + windows_xmm_save_bytes; + APPEND_M(str( "MOV RAX, RSP" )); + APPEND_M(str( "SUB RSP, #", to_hex(windows_frame_bytes + 63) )); + APPEND_M(str( "AND RSP, -64" )); + // Keep spill base (RSP+8) 64-byte aligned. + APPEND_M(str( "SUB RSP, 8" )); + APPEND_M(str( "MOV [RSP], RAX" )); + const int windows_xmm_save_base = windows_saved_rsp_bytes + spill_bytes + windows_shadow_space_bytes; + APPEND_M(str( "VMOVDQU [RSP+#], YMM6", to_hex(windows_xmm_save_base + 0 * 32) )); + APPEND_M(str( "VMOVDQU [RSP+#], YMM7", to_hex(windows_xmm_save_base + 1 * 32) )); + APPEND_M(str( "VMOVDQU [RSP+#], YMM8", to_hex(windows_xmm_save_base + 2 * 32) )); + APPEND_M(str( "VMOVDQU [RSP+#], YMM9", to_hex(windows_xmm_save_base + 3 * 32) )); + APPEND_M(str( "VMOVDQU [RSP+#], YMM10", to_hex(windows_xmm_save_base + 4 * 32) )); + APPEND_M(str( "VMOVDQU [RSP+#], YMM11", to_hex(windows_xmm_save_base + 5 * 32) )); + APPEND_M(str( "VMOVDQU [RSP+#], YMM12", to_hex(windows_xmm_save_base + 6 * 32) )); + APPEND_M(str( "VMOVDQU [RSP+#], YMM13", to_hex(windows_xmm_save_base + 7 * 32) )); + APPEND_M(str( "VMOVDQU [RSP+#], YMM14", to_hex(windows_xmm_save_base + 8 * 32) )); + APPEND_M(str( "VMOVDQU [RSP+#], YMM15", to_hex(windows_xmm_save_base + 9 * 32) )); +#else // RSP'=RSP&(~63) ; this makes it 64-aligned and can only reduce its value // RSP''=RSP'-64 ; still 64-aligned but now there is at least 64 bytes of unused stuff // [RSP'']=RSP ; store old value in unused area @@ -105,6 +147,7 @@ struct asm_function { APPEND_M(str( "AND RSP, -64" )); //-64 equals ~63 APPEND_M(str( "SUB RSP, 64" )); APPEND_M(str( "MOV [RSP], RAX" )); +#endif } } @@ -122,6 +165,21 @@ struct asm_function { //this takes 4 cycles including ret, if there is nothing else to do if (d_align_stack) { +#ifdef CHIA_WINDOWS + const int windows_saved_rsp_bytes = 8; + const int windows_shadow_space_bytes = 0x20; + const int windows_xmm_save_base = windows_saved_rsp_bytes + spill_bytes + windows_shadow_space_bytes; + APPEND_M(str( "VMOVDQU YMM6, [RSP+#]", to_hex(windows_xmm_save_base + 0 * 32) )); + APPEND_M(str( "VMOVDQU YMM7, [RSP+#]", to_hex(windows_xmm_save_base + 1 * 32) )); + APPEND_M(str( "VMOVDQU YMM8, [RSP+#]", to_hex(windows_xmm_save_base + 2 * 32) )); + APPEND_M(str( "VMOVDQU YMM9, [RSP+#]", to_hex(windows_xmm_save_base + 3 * 32) )); + APPEND_M(str( "VMOVDQU YMM10, [RSP+#]", to_hex(windows_xmm_save_base + 4 * 32) )); + APPEND_M(str( "VMOVDQU YMM11, [RSP+#]", to_hex(windows_xmm_save_base + 5 * 32) )); + APPEND_M(str( "VMOVDQU YMM12, [RSP+#]", to_hex(windows_xmm_save_base + 6 * 32) )); + APPEND_M(str( "VMOVDQU YMM13, [RSP+#]", to_hex(windows_xmm_save_base + 7 * 32) )); + APPEND_M(str( "VMOVDQU YMM14, [RSP+#]", to_hex(windows_xmm_save_base + 8 * 32) )); + APPEND_M(str( "VMOVDQU YMM15, [RSP+#]", to_hex(windows_xmm_save_base + 9 * 32) )); +#endif APPEND_M(str( "MOV RSP, [RSP]" )); } for (int x=pop_regs.size()-1;x>=0;--x) { diff --git a/src/avx512_integer.h b/src/avx512_integer.h index 9d683e7a..ee3cfc1e 100644 --- a/src/avx512_integer.h +++ b/src/avx512_integer.h @@ -124,7 +124,7 @@ void mpz_impl_set_mul( const mpz& b ) { #if defined(ARCH_X86) || defined(ARCH_X64) - if (enable_avx512_ifma) { + if (enable_avx512_ifma.load(std::memory_order_relaxed)) { typename avx512_integer_for_size::i a_avx512; typename avx512_integer_for_size::i b_avx512; typename avx512_integer_for_size::i out_avx512; diff --git a/src/avx512_test.cpp b/src/avx512_test.cpp index 9fab0b29..d4e5faab 100644 --- a/src/avx512_test.cpp +++ b/src/avx512_test.cpp @@ -80,7 +80,7 @@ int main(int argc, char **argv) { init_gmp(); set_rounding_mode(); - enable_avx512_ifma=false; + enable_avx512_ifma.store(false, std::memory_order_relaxed); if (argc==2 && string(argv[1]) == "avx512") { integer a_int=rand_integer(512); diff --git a/src/callback.h b/src/callback.h index a10cb054..9da2f9ce 100644 --- a/src/callback.h +++ b/src/callback.h @@ -33,7 +33,7 @@ class WesolowskiCallback :public INUDUPLListener { switch(type) { case NL_SQUARESTATE: { -#if defined(ARCH_X86) || defined(ARCH_X64) +#if (defined(ARCH_X86) || defined(ARCH_X64)) && !defined(CHIA_DISABLE_ASM) //cout << "NL_SQUARESTATE" << endl; uint64 res; diff --git a/src/generic.h b/src/generic.h index 2e3475bb..e0daa85d 100644 --- a/src/generic.h +++ b/src/generic.h @@ -71,7 +71,7 @@ template std::string to_string(std::ostringstream& s, const type& ta return s.str(); } template std::string to_string(const type& targ) { - static std::ostringstream s; + thread_local std::ostringstream s; return to_string(s, targ); } @@ -86,11 +86,11 @@ template type from_string(std::istringstream& s, const std::string& return checked_from_string(s, targ).first; } template type from_string(const std::string& targ) { - static std::istringstream s; + thread_local std::istringstream s; return from_string(s, targ); } template pair checked_from_string(const std::string& targ) { - static std::istringstream s; + thread_local std::istringstream s; return checked_from_string(s, targ); } diff --git a/src/include.h b/src/include.h index 63be0ae9..ecc23d1c 100644 --- a/src/include.h +++ b/src/include.h @@ -26,7 +26,12 @@ typedef unsigned __int128 uint128; typedef __int128 int128; #define USED __attribute__((used)) #else +#if defined(__clang__) && defined(__SIZEOF_INT128__) +typedef unsigned __int128 uint128; +typedef __int128 int128; +#else #include "uint128_t/uint128_t.h" +#endif #define USED #endif #include diff --git a/src/parameters.h b/src/parameters.h index 85481e4e..4b5160a8 100644 --- a/src/parameters.h +++ b/src/parameters.h @@ -29,10 +29,27 @@ extern int gcd_128_max_iter; extern std::string asmprefix; extern bool enable_all_instructions; -bool bChecked=false; -bool bAVX2=false; - -bool enable_avx512_ifma=false; +#include +#include +#include + +inline std::atomic bAVX2{false}; +inline std::atomic enable_avx512_ifma{false}; +inline std::once_flag avx_flags_once; + +inline bool env_flag(const char* name) { + const char* value = getenv(name); + if (!value) { + return false; + } + if (value[0] == '1' || value[0] == 'y' || value[0] == 'Y' || value[0] == 't' || value[0] == 'T') { + return true; + } + if (value[0] == '0' || value[0] == 'n' || value[0] == 'N' || value[0] == 'f' || value[0] == 'F') { + return false; + } + return true; +} #if defined(__i386) || defined(_M_IX86) #define ARCH_X86 @@ -48,12 +65,14 @@ bool enable_avx512_ifma=false; #define ARCH_32BIT #endif -inline bool hasAVX2() +inline void init_avx_flags() { - if(!bChecked) - { - bChecked=true; #if defined(ARCH_X86) || defined(ARCH_X64) + const bool disable_avx2 = env_flag("CHIA_DISABLE_AVX2"); + const bool force_avx2 = env_flag("CHIA_FORCE_AVX2"); + const bool disable_avx512 = env_flag("CHIA_DISABLE_AVX512_IFMA"); + const bool enable_avx512 = env_flag("CHIA_ENABLE_AVX512_IFMA"); + const bool force_avx512 = env_flag("CHIA_FORCE_AVX512_IFMA"); int info[4] = {0}; #if defined(_MSC_VER) __cpuid(info, 0x7); @@ -73,18 +92,44 @@ inline bool hasAVX2() #endif const int AVX2 = 1<<5; const int ADX = 1<<19; + const int AVX512F = 1<<16; + const int AVX512IFMA = 1<<21; bool avx2bit = ((info[1] & AVX2) == AVX2); bool adxbit = ((info[1] & ADX) == ADX); - bAVX2 = avx2bit && adxbit; + bool avx512fbit = ((info[1] & AVX512F) == AVX512F); + bool avx512ifmabit = ((info[1] & AVX512IFMA) == AVX512IFMA); + + if (disable_avx2) { + bAVX2.store(false, std::memory_order_relaxed); + } else if (force_avx2) { + bAVX2.store(true, std::memory_order_relaxed); + } else { + bAVX2.store(avx2bit && adxbit, std::memory_order_relaxed); + } + + if (disable_avx512) { + enable_avx512_ifma.store(false, std::memory_order_relaxed); + } else if (force_avx512) { + enable_avx512_ifma.store(true, std::memory_order_relaxed); + } else if (enable_avx512) { + enable_avx512_ifma.store(avx512fbit && avx512ifmabit, std::memory_order_relaxed); + } else { + enable_avx512_ifma.store(false, std::memory_order_relaxed); + } #elif defined(ARCH_ARM) - bAVX2 = false; + bAVX2.store(false, std::memory_order_relaxed); + enable_avx512_ifma.store(false, std::memory_order_relaxed); #else - bAVX2 = false; + bAVX2.store(false, std::memory_order_relaxed); + enable_avx512_ifma.store(false, std::memory_order_relaxed); #endif - } +} - return bAVX2; +inline bool hasAVX2() +{ + std::call_once(avx_flags_once, init_avx_flags); + return bAVX2.load(std::memory_order_relaxed); } /* diff --git a/src/prover_base.hpp b/src/prover_base.hpp index 2643a4a8..e9758d59 100644 --- a/src/prover_base.hpp +++ b/src/prover_base.hpp @@ -47,7 +47,7 @@ class Prover { id = form::identity(D); } catch(std::exception& e) { std::cout << "Warning: Could not create identity: " << e.what() << "\n"; - std::cout << "Discriminant: " << D.impl << "\n"; + std::cout << "Discriminant: " << D.to_string() << "\n"; std::cout << "Segment start:" << segm.start << "\n"; std::cout << "Segment length:" << segm.length << "\n"; std::cout << std::flush; diff --git a/src/prover_test.cpp b/src/prover_test.cpp index 7b453cd3..f0d5ed76 100644 --- a/src/prover_test.cpp +++ b/src/prover_test.cpp @@ -70,7 +70,7 @@ int main() { bool multi_proc_machine = (std::thread::hardware_concurrency() >= 16) ? true : false; WesolowskiCallback* weso = new FastAlgorithmCallback(segments, D, f, multi_proc_machine); - std::cout << "Discriminant: " << D.impl << "\n"; + std::cout << "Discriminant: " << D.to_string() << "\n"; std::atomic stopped = false; fast_algorithm = true; FastStorage* fast_storage = NULL; diff --git a/src/threading.h b/src/threading.h index 50d4b49a..3ba24596 100644 --- a/src/threading.h +++ b/src/threading.h @@ -7,8 +7,10 @@ //mp_limb_t is an unsigned integer static_assert(sizeof(mp_limb_t)==8, ""); +#ifndef _WIN32 static_assert(sizeof(unsigned long int)==8, ""); static_assert(sizeof(long int)==8, ""); +#endif static uint64 get_time_cycles() { // Returns the time in EDX:EAX. diff --git a/src/uint128_t/uint128_t.cpp b/src/uint128_t/uint128_t.cpp index ce5b74ef..89b90be8 100644 --- a/src/uint128_t/uint128_t.cpp +++ b/src/uint128_t/uint128_t.cpp @@ -435,7 +435,10 @@ std::string uint128_t::str(uint8_t base, const unsigned int & len) const{ std::pair qr(*this, uint128_0); do{ qr = divmod(qr.first, base); - out = "0123456789abcdef"[(uint8_t) qr.second] + out; + uint8_t digit = static_cast(qr.second); + char c = (digit < 10) ? static_cast('0' + digit) + : static_cast('a' + (digit - 10)); + out = c + out; } while (qr.first); } if (out.size() < len){ diff --git a/src/vdf.h b/src/vdf.h index e83c323a..42f41d14 100644 --- a/src/vdf.h +++ b/src/vdf.h @@ -3,7 +3,7 @@ #include "include.h" -#if defined(ARCH_X86) || defined(ARCH_X64) +#if (defined(ARCH_X86) || defined(ARCH_X64)) && !defined(CHIA_DISABLE_ASM) #include #endif @@ -26,7 +26,7 @@ #include "nudupl_listener.h" -#if defined(ARCH_X86) || defined(ARCH_X64) +#if (defined(ARCH_X86) || defined(ARCH_X64)) && !defined(CHIA_DISABLE_ASM) #include "asm_main.h" #include "gcd_base_continued_fractions.h" @@ -43,7 +43,7 @@ #include "gpu_integer_gcd.h" -#if defined(ARCH_X86) || defined(ARCH_X64) +#if (defined(ARCH_X86) || defined(ARCH_X64)) && !defined(CHIA_DISABLE_ASM) #include "vdf_test.h" #endif #include @@ -178,7 +178,7 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege f_copy=f; c_checkpoint_interval=1; - #if defined(ARCH_X86) || defined(ARCH_X64) + #if (defined(ARCH_X86) || defined(ARCH_X64)) && !defined(CHIA_DISABLE_ASM) f_copy_3=f; f_copy_3_valid=square_fast_impl(f_copy_3, D, L, num_iterations); #endif @@ -193,7 +193,7 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege #endif uint64 actual_iterations = 0; -#if defined(ARCH_X86) || defined(ARCH_X64) +#if (defined(ARCH_X86) || defined(ARCH_X64)) && !defined(CHIA_DISABLE_ASM) // x86/x64: use the phased pipeline. square_state_type square_state; square_state.pairindex = 0; diff --git a/src/vdf_bench.cpp b/src/vdf_bench.cpp index aab8feeb..a47a1da5 100644 --- a/src/vdf_bench.cpp +++ b/src/vdf_bench.cpp @@ -1,4 +1,5 @@ #include "include.h" +#include #include "bit_manipulation.h" #include "double_utility.h" #include "parameters.h" @@ -9,7 +10,7 @@ #include "picosha2.h" #include "proof_common.h" -#if defined(ARCH_X86) || defined(ARCH_X64) +#if (defined(ARCH_X86) || defined(ARCH_X64)) && !defined(CHIA_DISABLE_ASM) #include "asm_main.h" #include "threading.h" #include "avx512_integer.h" @@ -49,7 +50,7 @@ int main(int argc, char **argv) auto t1 = std::chrono::high_resolution_clock::now(); if (!strcmp(argv[1], "square_asm")) { is_asm = true; -#if defined(ARCH_X86) || defined(ARCH_X64) +#if (defined(ARCH_X86) || defined(ARCH_X64)) && !defined(CHIA_DISABLE_ASM) for (i = 0; i < iters; ) { square_state_type sq_state; sq_state.pairindex = 0; diff --git a/src/vdf_test.cpp b/src/vdf_test.cpp index 74a56afb..b2bd4b1d 100644 --- a/src/vdf_test.cpp +++ b/src/vdf_test.cpp @@ -280,8 +280,8 @@ int main(int argc, char* argv[]) { repeated_square c_square(d, d_initial, num_iterations); - cout << c_square.current.a.impl << "\n"; - cout << c_square.current.b.impl; + cout << c_square.current.a.to_string() << "\n"; + cout << c_square.current.b.to_string(); //track_max.output(512); From e7f37d746cf8c43bb86e30fd8a79a03247f5ca15 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 6 Feb 2026 18:38:59 -0800 Subject: [PATCH 02/78] CMake: Windows + perf experiment options --- src/CMakeLists.txt | 332 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b9c28bec..9da7c348 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,19 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.14 FATAL_ERROR) option(BUILD_CHIAVDFC "Build the chiavdfc shared library" OFF) option(BUILD_PYTHON "Build the python bindings for chiavdf" ON) +option(BUILD_VDF_CLIENT "Build the vdf_client binary" OFF) +option(BUILD_VDF_BENCH "Build the vdf_bench binary" OFF) +option(BUILD_VDF_TESTS "Build vdf test binaries (1weso/2weso/prover)" OFF) +option(BUILD_HW_TOOLS "Build hardware timelord tools" OFF) +option(ENABLE_GNU_ASM "Enable GNU-style asm pipeline on x86/x64" ON) option(HARDENING "Enable hardening" OFF) +option(CHIAVDF_USE_LTO "Enable LTO for perf experiments" OFF) +option(CHIAVDF_PGO_GENERATE "Enable PGO generate instrumentation" OFF) +set(CHIAVDF_PGO_USE "" CACHE STRING "Path to PGO profdata for use") +set(CHIAVDF_MARCH "" CACHE STRING "Override -march for perf experiments") +option(CHIAVDF_DISABLE_PIE "Disable PIE for perf experiments" OFF) +option(CHIAVDF_WINDOWS_DISABLE_SECURITY "Disable Windows security mitigations for perf experiments" OFF) +option(CHIAVDF_WINDOWS_USE_LLD "Use lld-link on Windows for perf experiments" OFF) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -20,11 +32,18 @@ set(CMAKE_MODULE_PATH if(MSVC) add_compile_options(/EHsc) + if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + # MSVC does not provide the GNU intrinsics headers used by compile_asm. + set(ENABLE_GNU_ASM OFF CACHE BOOL "Enable GNU-style asm pipeline on x86/x64" FORCE) + endif() else() add_compile_options("$<$:-Og>") endif() +find_package(Threads REQUIRED) + if(WIN32) + add_compile_definitions(CHIA_WINDOWS) set(MPIR_LIBRARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../mpir_gc_x64") set(MPIR_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../mpir_gc_x64") include_directories( @@ -40,6 +59,20 @@ if(WIN32) message(FATAL_ERROR "MPIR library not found") endif() + find_library( + MPIRXX_LIBRARY + NAMES mpirxx libmpirxx gmpxx libgmpxx + PATHS ${MPIR_LIBRARY_DIR} ${MPIR_LIBRARY_DIR}/lib ${MPIR_LIBRARY_DIR}/lib64 + NO_DEFAULT_PATH + ) + if(MPIRXX_LIBRARY) + message(STATUS "MPIRXX library found at ${MPIRXX_LIBRARY}") + set(GMPXX_LIBRARIES ${MPIRXX_LIBRARY}) + link_libraries(${MPIRXX_LIBRARY}) + else() + message(WARNING "MPIRXX library not found; gmpxx iostream operators may be missing") + endif() + list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../mpir_gc_x64") else() find_package(GMP REQUIRED) @@ -56,6 +89,88 @@ endif() # CMake 3.14+ include(FetchContent) +set(VDF_COMMON_DEFINITIONS VDF_MODE=0 FAST_MACHINE=1) +set(VDF_COMMON_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/refcode/lzcnt.c +) +if(WIN32) + list(APPEND VDF_COMMON_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/uint128_t/uint128_t.cpp + ) +endif() + +set(VDF_ASM_SOURCES) +if(ENABLE_GNU_ASM AND (CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|AMD64|i[3-6]86)$")) + enable_language(ASM) + add_executable(compile_asm EXCLUDE_FROM_ALL + ${CMAKE_CURRENT_SOURCE_DIR}/compile_asm.cpp + ) + target_compile_definitions(compile_asm PRIVATE ${VDF_COMMON_DEFINITIONS}) + if(WIN32) + target_compile_definitions(compile_asm PRIVATE CHIA_WINDOWS) + endif() + target_link_libraries(compile_asm PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + if(WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + execute_process( + COMMAND ${CMAKE_CXX_COMPILER} --print-resource-dir + OUTPUT_VARIABLE CLANG_RESOURCE_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + set(CLANG_BUILTINS_LIB "${CLANG_RESOURCE_DIR}/lib/windows/clang_rt.builtins-x86_64.lib") + if(EXISTS "${CLANG_BUILTINS_LIB}") + target_link_libraries(compile_asm PRIVATE "${CLANG_BUILTINS_LIB}") + else() + message(FATAL_ERROR "clang_rt builtins not found: ${CLANG_BUILTINS_LIB}") + endif() + endif() + + set(ASM_COMPILED ${CMAKE_CURRENT_BINARY_DIR}/asm_compiled.s) + set(ASM_AVX2_COMPILED ${CMAKE_CURRENT_BINARY_DIR}/avx2_asm_compiled.s) + set(ASM_AVX512_COMPILED ${CMAKE_CURRENT_BINARY_DIR}/avx512_asm_compiled.s) + + set(ASM_ENV) + if(WIN32) + set(ASM_PATH "$ENV{PATH}") + string(REPLACE ";" "\\;" ASM_PATH_ESC "${ASM_PATH}") + set(ASM_ENV + ${CMAKE_COMMAND} -E env + "PATH=${CMAKE_CURRENT_SOURCE_DIR}/../mpir_gc_x64\\;${ASM_PATH_ESC}" + ) + endif() + + add_custom_command( + OUTPUT ${ASM_COMPILED} + COMMAND ${ASM_ENV} compile_asm + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS compile_asm + ) + add_custom_command( + OUTPUT ${ASM_AVX2_COMPILED} + COMMAND ${ASM_ENV} compile_asm avx2 + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS compile_asm + ) + add_custom_command( + OUTPUT ${ASM_AVX512_COMPILED} + COMMAND ${ASM_ENV} compile_asm avx512 + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS compile_asm + ) + + set_source_files_properties( + ${ASM_COMPILED} + ${ASM_AVX2_COMPILED} + ${ASM_AVX512_COMPILED} + PROPERTIES GENERATED TRUE + ) + + list(APPEND VDF_ASM_SOURCES + ${ASM_COMPILED} + ${ASM_AVX2_COMPILED} + ${ASM_AVX512_COMPILED} + ) +endif() + if(BUILD_PYTHON) FetchContent_Declare( pybind11-src @@ -80,6 +195,223 @@ if(BUILD_PYTHON) endif() endif() +set(HAVE_BOOST_HEADERS FALSE) +set(NEED_BOOST_HEADERS FALSE) +if(BUILD_VDF_CLIENT OR BUILD_VDF_TESTS OR BUILD_HW_TOOLS) + set(NEED_BOOST_HEADERS TRUE) +endif() + +if(NEED_BOOST_HEADERS) + if(WIN32) + find_path(BOOST_INCLUDE_DIR boost/asio.hpp) + if(BOOST_INCLUDE_DIR) + set(HAVE_BOOST_HEADERS TRUE) + endif() + else() + find_package(Boost REQUIRED) + set(HAVE_BOOST_HEADERS TRUE) + endif() +endif() + +function(vdf_add_boost_includes target_name) + if(NEED_BOOST_HEADERS AND HAVE_BOOST_HEADERS) + if(WIN32) + target_include_directories(${target_name} PRIVATE ${BOOST_INCLUDE_DIR}) + else() + target_include_directories(${target_name} PRIVATE ${Boost_INCLUDE_DIRS}) + endif() + endif() +endfunction() + +function(vdf_add_windows_asm_linker_flags target_name) + if(WIN32 AND ENABLE_GNU_ASM) + # chiavdf asm uses absolute 32-bit relocations on Windows + target_link_options(${target_name} PRIVATE "LINKER:/LARGEADDRESSAWARE:NO") + endif() +endfunction() + +function(vdf_add_windows_clang_opts target_name) + if(WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + target_compile_options( + ${target_name} + PRIVATE + "$<$:-O3>" + "$<$:-ffp-contract=fast>" + "$<$:-fno-math-errno>" + ) + endif() +endfunction() + +function(vdf_add_perf_opts target_name) + if(CHIAVDF_USE_LTO) + set_property(TARGET ${target_name} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) + endif() + if(CHIAVDF_DISABLE_PIE) + target_compile_options(${target_name} PRIVATE "$<$:-fno-pie>") + target_link_options(${target_name} PRIVATE -no-pie) + endif() + if(CHIAVDF_MARCH) + if(MSVC) + target_compile_options(${target_name} PRIVATE "$<$:/clang:-march=${CHIAVDF_MARCH}>") + else() + target_compile_options(${target_name} PRIVATE "$<$:-march=${CHIAVDF_MARCH}>") + endif() + endif() + if(CHIAVDF_PGO_GENERATE) + target_compile_options(${target_name} PRIVATE "$<$:-fprofile-instr-generate>") + target_link_options(${target_name} PRIVATE -fprofile-instr-generate) + endif() + if(CHIAVDF_PGO_USE) + target_compile_options(${target_name} PRIVATE "$<$:-fprofile-instr-use=${CHIAVDF_PGO_USE}>") + target_link_options(${target_name} PRIVATE "-fprofile-instr-use=${CHIAVDF_PGO_USE}") + endif() + if(WIN32 AND CHIAVDF_WINDOWS_DISABLE_SECURITY) + if(MSVC) + target_compile_options(${target_name} PRIVATE /GS-) + target_link_options(${target_name} PRIVATE "LINKER:/guard:cf-") + else() + target_compile_options(${target_name} PRIVATE "$<$:-fno-stack-protector>") + target_link_options(${target_name} PRIVATE "-Wl,/guard:cf-") + endif() + endif() + if(WIN32 AND CHIAVDF_WINDOWS_USE_LLD AND NOT MSVC) + target_link_options(${target_name} PRIVATE -fuse-ld=lld) + endif() +endfunction() + +if(BUILD_VDF_CLIENT) + add_executable(vdf_client + ${CMAKE_CURRENT_SOURCE_DIR}/vdf_client.cpp + ) + target_sources(vdf_client PRIVATE ${VDF_COMMON_SOURCES} ${VDF_ASM_SOURCES}) + target_compile_definitions(vdf_client PRIVATE ${VDF_COMMON_DEFINITIONS}) + if(NOT HAVE_BOOST_HEADERS) + message(FATAL_ERROR "Boost headers not found (needed for vdf_client)") + endif() + vdf_add_boost_includes(vdf_client) + target_link_libraries(vdf_client PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + vdf_add_windows_asm_linker_flags(vdf_client) + vdf_add_windows_clang_opts(vdf_client) + vdf_add_perf_opts(vdf_client) +endif() + +if(BUILD_VDF_BENCH) + add_executable(vdf_bench + ${CMAKE_CURRENT_SOURCE_DIR}/vdf_bench.cpp + ) + target_sources(vdf_bench PRIVATE ${VDF_COMMON_SOURCES} ${VDF_ASM_SOURCES}) + target_compile_definitions(vdf_bench PRIVATE ${VDF_COMMON_DEFINITIONS}) + target_link_libraries(vdf_bench PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + vdf_add_windows_asm_linker_flags(vdf_bench) + vdf_add_windows_clang_opts(vdf_bench) + vdf_add_perf_opts(vdf_bench) +endif() + +if(BUILD_VDF_TESTS) + add_executable(1weso_test + ${CMAKE_CURRENT_SOURCE_DIR}/1weso_test.cpp + ) + target_sources(1weso_test PRIVATE ${VDF_COMMON_SOURCES} ${VDF_ASM_SOURCES}) + target_compile_definitions(1weso_test PRIVATE ${VDF_COMMON_DEFINITIONS}) + if(WIN32) + target_compile_definitions(1weso_test PRIVATE CHIA_DISABLE_ASM) + endif() + vdf_add_boost_includes(1weso_test) + target_link_libraries(1weso_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + + add_executable(2weso_test + ${CMAKE_CURRENT_SOURCE_DIR}/2weso_test.cpp + ) + target_sources(2weso_test PRIVATE ${VDF_COMMON_SOURCES} ${VDF_ASM_SOURCES}) + target_compile_definitions(2weso_test PRIVATE ${VDF_COMMON_DEFINITIONS}) + if(WIN32) + target_compile_definitions(2weso_test PRIVATE CHIA_DISABLE_ASM) + endif() + vdf_add_boost_includes(2weso_test) + target_link_libraries(2weso_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + + add_executable(prover_test + ${CMAKE_CURRENT_SOURCE_DIR}/prover_test.cpp + ) + target_sources(prover_test PRIVATE ${VDF_COMMON_SOURCES} ${VDF_ASM_SOURCES}) + target_compile_definitions(prover_test PRIVATE ${VDF_COMMON_DEFINITIONS}) + if(WIN32) + target_compile_definitions(prover_test PRIVATE CHIA_DISABLE_ASM) + endif() + vdf_add_boost_includes(prover_test) + target_link_libraries(prover_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) +endif() + +if(BUILD_HW_TOOLS) + set(HW_COMMON_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/vdf_base.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_util.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_proof.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_interface.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/hw/chia_driver.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/hw/ftdi_driver.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/hw/vdf_driver.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/hw/pll_freqs.cpp + ) + set(EMU_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/hw/emu_funcs.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/hw/emu_runner.cpp + ) + + if(NOT WIN32) + if(APPLE) + set(HW_LIBS + ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222/libft4222.dylib + ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222/libftd2xx.dylib + ) + else() + set(HW_LIBS + ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222/build-x86_64/libft4222.so + ) + endif() + + add_executable(hw_test + ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/hw/real_hw.cpp + ) + target_sources(hw_test PRIVATE ${HW_COMMON_SOURCES} ${VDF_ASM_SOURCES} ${VDF_COMMON_SOURCES}) + target_compile_definitions(hw_test PRIVATE ${VDF_COMMON_DEFINITIONS}) + target_include_directories(hw_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/hw ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222) + target_link_libraries(hw_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads ${HW_LIBS}) + if(APPLE) + target_link_options(hw_test PRIVATE "-Wl,-rpath,@executable_path/hw/libft4222") + endif() + + add_executable(hw_vdf_client + ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_vdf_client.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/hw/real_hw.cpp + ) + target_sources(hw_vdf_client PRIVATE ${HW_COMMON_SOURCES} ${VDF_ASM_SOURCES} ${VDF_COMMON_SOURCES}) + target_compile_definitions(hw_vdf_client PRIVATE ${VDF_COMMON_DEFINITIONS}) + target_include_directories(hw_vdf_client PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/hw ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222) + target_link_libraries(hw_vdf_client PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads ${HW_LIBS}) + if(APPLE) + target_link_options(hw_vdf_client PRIVATE "-Wl,-rpath,@executable_path/hw/libft4222") + endif() + endif() + + add_executable(emu_hw_test + ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_test.cpp + ) + target_sources(emu_hw_test PRIVATE ${HW_COMMON_SOURCES} ${EMU_SOURCES} ${VDF_ASM_SOURCES} ${VDF_COMMON_SOURCES}) + target_compile_definitions(emu_hw_test PRIVATE ${VDF_COMMON_DEFINITIONS}) + target_include_directories(emu_hw_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/hw ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222) + target_link_libraries(emu_hw_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + + add_executable(emu_hw_vdf_client + ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_vdf_client.cpp + ) + target_sources(emu_hw_vdf_client PRIVATE ${HW_COMMON_SOURCES} ${EMU_SOURCES} ${VDF_ASM_SOURCES} ${VDF_COMMON_SOURCES}) + target_compile_definitions(emu_hw_vdf_client PRIVATE ${VDF_COMMON_DEFINITIONS}) + target_include_directories(emu_hw_vdf_client PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/hw ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222) + target_link_libraries(emu_hw_vdf_client PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) +endif() + add_executable(verifier_test ${CMAKE_CURRENT_SOURCE_DIR}/verifier_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/refcode/lzcnt.c From 003ecf3ce145ba948f04afc56fea1307e5711fad Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 6 Feb 2026 18:39:08 -0800 Subject: [PATCH 03/78] CI: perf experiments and Windows benchmarking --- .github/workflows/test.yaml | 420 +++++++++++++++++++++++++++++++++++- WINDOWS_PERF_NOTES.md | 25 +++ 2 files changed, 440 insertions(+), 5 deletions(-) create mode 100644 WINDOWS_PERF_NOTES.md diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 729e19ee..62c92f6c 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -17,8 +17,13 @@ jobs: strategy: fail-fast: false matrix: - os: [macos-13-intel, macos-13-arm64, ubuntu-latest] + os: [macos-13-intel, macos-13-arm64, ubuntu-latest, windows-latest] config: [optimized=1, TSAN=1, ASAN=1] + exclude: + - os: windows-latest + config: TSAN=1 + - os: windows-latest + config: ASAN=1 steps: - name: Checkout code @@ -47,8 +52,42 @@ jobs: cd src make ${{ matrix.config }} -f Makefile.vdf-client + - name: Install LLVM and Ninja on Windows + if: startsWith(matrix.os, 'windows') + shell: pwsh + run: | + choco install llvm ninja boost-msvc-14.3 -y + "C:\Program Files\LLVM\bin" | Out-File -Append -FilePath $env:GITHUB_PATH + $boostDir = Get-ChildItem "C:\local" -Directory -Filter "boost_*" | Select-Object -First 1 + if (-not $boostDir) { + throw "Boost install not found under C:\local" + } + "BOOST_INCLUDE_DIR=$($boostDir.FullName)" | Out-File -Append -FilePath $env:GITHUB_ENV + + - name: Checkout mpir for Windows + if: startsWith(matrix.os, 'windows') + uses: actions/checkout@v6 + with: + repository: Chia-Network/mpir_gc_x64 + fetch-depth: 1 + path: mpir_gc_x64 + + - name: Build vdf-client on Windows + if: startsWith(matrix.os, 'windows') + shell: pwsh + run: | + cmake -S src -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_ASM_COMPILER=clang -DBOOST_INCLUDE_DIR="$env:BOOST_INCLUDE_DIR" -DBUILD_PYTHON=OFF -DBUILD_CHIAVDFC=OFF -DBUILD_VDF_CLIENT=ON -DBUILD_VDF_BENCH=ON -DBUILD_VDF_TESTS=ON -DBUILD_HW_TOOLS=OFF + cmake --build build --target vdf_client vdf_bench 1weso_test 2weso_test prover_test + + - name: Benchmark vdf_bench square (Unix) + if: "!startsWith(matrix.os, 'windows')" + run: | + cd src + echo "Benchmarking vdf_bench with 2,500,000 iterations of square_asm" + ./vdf_bench square_asm 2500000 + - name: Test vdf-client - if: matrix.config == 'optimized=1' + if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') run: | cd src echo "Running 1weso_test" @@ -63,7 +102,7 @@ jobs: fi - name: Test vdf-client - if: matrix.config != 'optimized=1' + if: matrix.config != 'optimized=1' && !startsWith(matrix.os, 'windows') run: | cd src echo "Running 1weso_test" @@ -75,7 +114,7 @@ jobs: # it prints to std::cout from multiple threads. Which is allowed by the # standard - name: test Prover - if: matrix.config != 'optimized=1' && (matrix.config != 'TSAN=1' || startsWith(matrix.os, 'ubuntu')) + if: matrix.config != 'optimized=1' && (matrix.config != 'TSAN=1' || startsWith(matrix.os, 'ubuntu')) && !startsWith(matrix.os, 'windows') run: | cd src echo "Running prover_test" @@ -85,9 +124,380 @@ jobs: CHIAVDF_PROVER_TEST_FAST=1 ./prover_test fi + - name: Test vdf-client (Windows) + if: matrix.config == 'optimized=1' && startsWith(matrix.os, 'windows') + shell: pwsh + run: | + cd build + $dllPaths = @() + if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } + if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } + if ($dllPaths.Count -gt 0) { $env:PATH = ($dllPaths -join ';') + ';' + $env:PATH } + Write-Host "Running 1weso_test" + .\1weso_test.exe + Write-Host "Running 2weso_test" + .\2weso_test.exe + Write-Host "Running prover_test" + $env:CHIAVDF_PROVER_TEST_FAST = "1" + .\prover_test.exe + - name: Benchmark vdf-client - if: matrix.config == 'optimized=1' + if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') run: | cd src echo "Benchmarking vdf_client with 400,000 iterations of vdf_bench" ./vdf_bench square_asm 400000 + + - name: Benchmark vdf-client (Windows) + if: matrix.config == 'optimized=1' && startsWith(matrix.os, 'windows') + shell: pwsh + run: | + cd build + $dllPaths = @() + if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } + if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } + if ($dllPaths.Count -gt 0) { $env:PATH = ($dllPaths -join ';') + ';' + $env:PATH } + Write-Host "Benchmarking vdf_client with 400,000 iterations of vdf_bench" + & .\vdf_bench.exe square_asm 400000 + Write-Host "vdf_bench exit code: $LASTEXITCODE" + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + + - name: Profile vdf_bench square (Windows) + if: matrix.config == 'optimized=1' && startsWith(matrix.os, 'windows') + shell: pwsh + run: | + cd build + $dllPaths = @() + if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } + if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } + if ($dllPaths.Count -gt 0) { $env:PATH = ($dllPaths -join ';') + ';' + $env:PATH } + Write-Host "Profiling vdf_bench square with 200,000 iterations" + & .\vdf_bench.exe square 200000 + + - name: Benchmark vdf_bench square (Unix) + if: "!startsWith(matrix.os, 'windows')" + run: | + cd src + echo "Benchmarking vdf_bench with 1,000,000 iterations of square_asm" + ./vdf_bench square_asm 1000000 + + - name: Profile vdf_bench square (Unix) + if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') + run: | + cd src + echo "Profiling vdf_bench square with 200,000 iterations" + ./vdf_bench square 200000 + + - name: Benchmark vdf_bench square (Windows) + if: startsWith(matrix.os, 'windows') + shell: pwsh + run: | + cd build + $dllPaths = @() + if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } + if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } + if ($dllPaths.Count -gt 0) { $env:PATH = ($dllPaths -join ';') + ';' + $env:PATH } + Write-Host "Benchmarking vdf_bench with 1,000,000 iterations of square_asm" + & .\vdf_bench.exe square_asm 1000000 + Write-Host "vdf_bench exit code: $LASTEXITCODE" + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + + perf_experiments: + name: Perf experiments ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest] + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Install perf deps (Ubuntu) + if: startsWith(matrix.os, 'ubuntu') + run: | + sudo apt-get update -y -o Acquire::Retries=3 + sudo apt-get install -y clang llvm lld ninja-build libgmp-dev gcc + + - name: Install perf deps (Windows) + if: startsWith(matrix.os, 'windows') + shell: pwsh + run: | + choco install llvm ninja -y + "C:\Program Files\LLVM\bin" | Out-File -Append -FilePath $env:GITHUB_PATH + + - name: Checkout mpir for Windows + if: startsWith(matrix.os, 'windows') + uses: actions/checkout@v6 + with: + repository: Chia-Network/mpir_gc_x64 + fetch-depth: 1 + path: mpir_gc_x64 + + - name: Run perf experiments (Ubuntu) + if: startsWith(matrix.os, 'ubuntu') + run: | + set -euo pipefail + set -x + trap 'echo "perf_experiments ubuntu failed"; find . -maxdepth 3 -type f -name "vdf_bench" -print; find . -maxdepth 3 -type f -name "CMakeCache.txt" -print' ERR + mkdir -p pgo + variants=("baseline" "lto" "march" "lto-march" "pgo" "pgo-march") + baseline_speed="" + + run_bench() { + local build_dir="$1" + local build_log="${build_dir}/build.log" + if ! cmake --build "$build_dir" --target vdf_bench 2>&1 | tee "$build_log" >&2; then + echo "vdf_bench build failed for ${build_dir}" >&2 + cat "$build_log" >&2 + return 1 + fi + local out_file="${build_dir}/bench.out" + local bench_path + bench_path="$(find "${build_dir}" -name vdf_bench -type f -print -quit)" + if [[ -z "${bench_path}" ]]; then + echo "vdf_bench not found under ${build_dir}" >&2 + find "${build_dir}" -maxdepth 3 -type f -print >&2 + return 1 + fi + "${bench_path}" square_asm 1000000 2>&1 | tee "$out_file" >&2 + local speed + speed="$(python -c 'import re,sys,pathlib; text=pathlib.Path(sys.argv[1]).read_text(errors="replace"); m=re.search(r"speed:\s*([0-9]+(?:\.[0-9]+)?)K ips", text); sys.exit("speed not found") if not m else None; print(m.group(1))' "$out_file")" + printf '%s\n' "$speed" + } + + for variant in "${variants[@]}"; do + echo "== perf variant: ${variant} ==" + build_dir="build-perf-${variant}" + cmake_flags=( + -S src + -B "${build_dir}" + -G Ninja + -DCMAKE_BUILD_TYPE=Release + -DCMAKE_C_COMPILER=clang + -DCMAKE_CXX_COMPILER=clang++ + -DCMAKE_ASM_COMPILER=gcc + -DCHIAVDF_DISABLE_PIE=ON + -DBUILD_PYTHON=OFF + -DBUILD_CHIAVDFC=OFF + -DBUILD_VDF_CLIENT=OFF + -DBUILD_VDF_BENCH=ON + -DBUILD_VDF_TESTS=OFF + -DBUILD_HW_TOOLS=OFF + ) + cmake_flags+=(-DCMAKE_POSITION_INDEPENDENT_CODE=OFF) + cmake_flags+=(-DCMAKE_EXE_LINKER_FLAGS=-no-pie) + if [[ "$variant" == *"lto"* ]]; then + cmake_flags+=(-DCHIAVDF_USE_LTO=ON) + fi + if [[ "$variant" == *"march"* ]]; then + cmake_flags+=(-DCHIAVDF_MARCH=x86-64-v3) + fi + + if [[ "$variant" == pgo* ]]; then + gen_dir="${build_dir}-gen" + use_dir="${build_dir}-use" + cmake "${cmake_flags[@]}" -B "${gen_dir}" -DCHIAVDF_PGO_GENERATE=ON + cmake --build "${gen_dir}" --target vdf_bench + gen_bench_path="$(find "${gen_dir}" -name vdf_bench -type f -print -quit)" + if [[ -z "${gen_bench_path}" ]]; then + echo "vdf_bench not found under ${gen_dir}" + find "${gen_dir}" -maxdepth 3 -type f -print + exit 1 + fi + LLVM_PROFILE_FILE="$(pwd)/pgo/${variant}.profraw" "${gen_bench_path}" square_asm 200000 >/dev/null + llvm-profdata merge -output="pgo/${variant}.profdata" "pgo/${variant}.profraw" + cmake "${cmake_flags[@]}" -B "${use_dir}" -DCHIAVDF_PGO_USE="$(pwd)/pgo/${variant}.profdata" + if ! speed=$(run_bench "${use_dir}"); then + echo "run_bench failed for ${use_dir}" + exit 1 + fi + else + cmake "${cmake_flags[@]}" + if ! speed=$(run_bench "${build_dir}"); then + echo "run_bench failed for ${build_dir}" + exit 1 + fi + fi + + if [[ -z "${baseline_speed}" ]]; then + baseline_speed="${speed}" + echo "PERF baseline speed=${speed}K ips" + if [[ "${variant}" == "baseline" ]]; then + hash_out="asm_hashes_ubuntu.txt" + find "${build_dir}" -name '*_asm_compiled.s' -type f -print | sort | while read -r asm_file; do + sha256sum "$asm_file" + done | tee "${hash_out}" + fi + else + delta=$(python -c 'import sys; base=float(sys.argv[1]); cur=float(sys.argv[2]); print(round((cur/base - 1.0) * 100.0, 1))' "${baseline_speed}" "${speed}") + echo "PERF variant=${variant} speed=${speed}K ips baseline=${baseline_speed}K ips delta=${delta}%" + fi + done + + - name: Run perf experiments (Windows) + if: startsWith(matrix.os, 'windows') + shell: pwsh + run: | + $ErrorActionPreference = "Stop" + $dllPaths = @() + if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } + if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } + if ($dllPaths.Count -gt 0) { $env:PATH = ($dllPaths -join ';') + ';' + $env:PATH } + $variants = @( + "baseline", + "lto", + "march", + "lto-march", + "pgo", + "pgo-march", + "clangcl", + "clangcl-lto", + "clangcl-march", + "clangcl-lto-march", + "clangcl-nosec", + "clangcl-lto-nosec", + "lld-lto" + ) + $baselineSpeed = $null + New-Item -ItemType Directory -Force -Path pgo | Out-Null + + function Get-SpeedFromOutput($output) { + $match = $output | Select-String -Pattern "speed:\s*([0-9\.]+)K ips" | Select-Object -First 1 + if (-not $match) { throw "speed not found" } + return [double]$match.Matches[0].Groups[1].Value + } + + function Run-Bench($buildDir) { + cmake --build $buildDir --target vdf_bench | ForEach-Object { Write-Host $_ } + $outPath = "$buildDir\bench.out" + $benchPath = (Get-ChildItem -Path $buildDir -Recurse -Filter vdf_bench.exe | Select-Object -First 1).FullName + if (-not $benchPath) { + Write-Host "vdf_bench.exe not found under $buildDir" + Get-ChildItem -Path $buildDir -Recurse -File | ForEach-Object { $_.FullName } + throw "vdf_bench.exe not found under $buildDir" + } + $out = & $benchPath square_asm 1000000 2>&1 + $outText = [string]::Join("`n", $out) + $outText | Set-Content -Path $outPath + $out | ForEach-Object { Write-Host $_ } + $script:LastBenchPath = $benchPath + try { + return (Get-SpeedFromOutput $outText) + } catch { + Write-Host "Failed to parse speed from $outPath" + $out | ForEach-Object { Write-Host $_ } + throw + } + } + + function Try-Profile($benchPath) { + if (-not $benchPath) { return } + $wpr = Get-Command wpr.exe -ErrorAction SilentlyContinue + if (-not $wpr) { + Write-Host "wpr.exe not found; skipping profile capture" + return + } + $tracePath = Join-Path $env:GITHUB_WORKSPACE "wpr-baseline.etl" + try { + wpr -start CPU | Out-Null + & $benchPath square_asm 200000 | Out-Null + wpr -stop $tracePath | Out-Null + } catch { + Write-Host "wpr capture failed: $_" + try { wpr -cancel | Out-Null } catch { } + } + } + + foreach ($variant in $variants) { + Write-Host "== perf variant: $variant ==" + $buildDir = "build-perf-$variant" + $useClangCl = $variant -like "clangcl*" + $cmakeArgs = @( + "-S", "src", + "-B", $buildDir, + "-G", "Ninja", + "-DCMAKE_BUILD_TYPE=Release", + "-DCMAKE_ASM_COMPILER=clang", + "-DBUILD_PYTHON=OFF", + "-DBUILD_CHIAVDFC=OFF", + "-DBUILD_VDF_CLIENT=OFF", + "-DBUILD_VDF_BENCH=ON", + "-DBUILD_VDF_TESTS=OFF", + "-DBUILD_HW_TOOLS=OFF" + ) + if ($useClangCl) { + $cmakeArgs += "-DCMAKE_C_COMPILER=clang-cl" + $cmakeArgs += "-DCMAKE_CXX_COMPILER=clang-cl" + } else { + $cmakeArgs += "-DCMAKE_C_COMPILER=clang" + $cmakeArgs += "-DCMAKE_CXX_COMPILER=clang++" + } + if ($variant -like "*lto*") { + $cmakeArgs += "-DCHIAVDF_USE_LTO=ON" + } + if ($variant -like "*march*") { + $cmakeArgs += "-DCHIAVDF_MARCH=x86-64-v3" + } + if ($variant -like "*nosec*") { + $cmakeArgs += "-DCHIAVDF_WINDOWS_DISABLE_SECURITY=ON" + } + if ($variant -like "*lld*") { + $cmakeArgs += "-DCHIAVDF_WINDOWS_USE_LLD=ON" + } + + if ($variant -like "pgo*") { + $genDir = "$buildDir-gen" + $useDir = "$buildDir-use" + cmake @cmakeArgs -B $genDir -DCHIAVDF_PGO_GENERATE=ON + cmake --build $genDir --target vdf_bench + $env:LLVM_PROFILE_FILE = "$(Get-Location)\pgo\$variant.profraw" + $genBenchPath = (Get-ChildItem -Path $genDir -Recurse -Filter vdf_bench.exe | Select-Object -First 1).FullName + if (-not $genBenchPath) { throw "vdf_bench.exe not found under $genDir" } + & $genBenchPath square_asm 200000 | Out-Null + & llvm-profdata merge -output "pgo\$variant.profdata" "pgo\$variant.profraw" + cmake @cmakeArgs -B $useDir -DCHIAVDF_PGO_USE="$(Get-Location)\pgo\$variant.profdata" + $speed = [double](Run-Bench $useDir) + } else { + cmake @cmakeArgs + $speed = [double](Run-Bench $buildDir) + } + + if (-not $baselineSpeed) { + $baselineSpeed = [double]$speed + Write-Host ("PERF baseline speed={0}K ips" -f $speed) + $hashOut = Join-Path $env:GITHUB_WORKSPACE "asm_hashes_windows.txt" + Get-ChildItem -Path $buildDir -Recurse -Filter "*_asm_compiled.s" | Sort-Object FullName | ForEach-Object { + $hash = Get-FileHash -Algorithm SHA256 $_.FullName + "{0} {1}" -f $hash.Hash, $hash.Path + } | Tee-Object -FilePath $hashOut | ForEach-Object { Write-Host $_ } + Try-Profile $script:LastBenchPath + } else { + $delta = [math]::Round((($speed / $baselineSpeed) - 1) * 100, 1) + Write-Host ("PERF variant={0} speed={1}K ips baseline={2}K ips delta={3}%" -f $variant, $speed, $baselineSpeed, $delta) + } + } + + - name: Upload asm hashes (Ubuntu) + if: startsWith(matrix.os, 'ubuntu') + uses: actions/upload-artifact@v4 + with: + name: asm-hashes-ubuntu + path: asm_hashes_ubuntu.txt + if-no-files-found: ignore + + - name: Upload asm hashes (Windows) + if: startsWith(matrix.os, 'windows') + uses: actions/upload-artifact@v4 + with: + name: asm-hashes-windows + path: asm_hashes_windows.txt + if-no-files-found: ignore + + - name: Upload Windows perf trace + if: startsWith(matrix.os, 'windows') + uses: actions/upload-artifact@v4 + with: + name: windows-perf-trace + path: wpr-baseline.etl + if-no-files-found: ignore diff --git a/WINDOWS_PERF_NOTES.md b/WINDOWS_PERF_NOTES.md new file mode 100644 index 00000000..643742ef --- /dev/null +++ b/WINDOWS_PERF_NOTES.md @@ -0,0 +1,25 @@ +# Windows perf notes (vdf_bench square_asm) + +## Summary +- Ubuntu baseline: ~160.3K ips +- Windows baseline: ~128.3K ips +- Gap: ~20% slower on Windows in current clang++ GNU-style asm build + +## Ubuntu perf experiment deltas +- lto: -0.7% +- march: -2.1% +- lto-march: 0.0% +- pgo: -0.5% +- pgo-march: -0.9% + +## Windows perf experiment deltas +- lto: -10.4% +- march: +0.4% +- lto-march: +0.9% +- pgo: +1.3% +- pgo-march: -4.1% + +## Next investigation hooks (in CI) +- Baseline asm hashes are captured for Ubuntu/Windows to compare generated `.s`. +- Optional Windows WPR trace (`wpr-baseline.etl`) is captured when available. +- Additional Windows variants (clang-cl, lld-link, nosec) are available for parity testing. From b1d905772545d48e9fc2ffc258cc973532c4b288 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Sat, 7 Feb 2026 15:25:03 -0800 Subject: [PATCH 04/78] ci: streamline test workflow --- .github/workflows/test.yaml | 368 +----------------------------------- 1 file changed, 10 insertions(+), 358 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 62c92f6c..0d8393ca 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -14,16 +14,13 @@ jobs: test: name: Test ${{ matrix.config }} ${{ matrix.os }} runs-on: ${{ matrix.os }} + env: + CHIAVDF_LOG_AVX: "1" strategy: fail-fast: false matrix: os: [macos-13-intel, macos-13-arm64, ubuntu-latest, windows-latest] config: [optimized=1, TSAN=1, ASAN=1] - exclude: - - os: windows-latest - config: TSAN=1 - - os: windows-latest - config: ASAN=1 steps: - name: Checkout code @@ -48,7 +45,7 @@ jobs: - name: Build vdf-client on Mac if: startsWith(matrix.os, 'mac') run: | - brew install boost + brew --prefix --installed boost >/dev/null 2>&1 || brew install boost cd src make ${{ matrix.config }} -f Makefile.vdf-client @@ -58,6 +55,7 @@ jobs: run: | choco install llvm ninja boost-msvc-14.3 -y "C:\Program Files\LLVM\bin" | Out-File -Append -FilePath $env:GITHUB_PATH + "CHIA_ENABLE_AVX512_IFMA=0" | Out-File -Append -FilePath $env:GITHUB_ENV $boostDir = Get-ChildItem "C:\local" -Directory -Filter "boost_*" | Select-Object -First 1 if (-not $boostDir) { throw "Boost install not found under C:\local" @@ -76,16 +74,9 @@ jobs: if: startsWith(matrix.os, 'windows') shell: pwsh run: | - cmake -S src -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_ASM_COMPILER=clang -DBOOST_INCLUDE_DIR="$env:BOOST_INCLUDE_DIR" -DBUILD_PYTHON=OFF -DBUILD_CHIAVDFC=OFF -DBUILD_VDF_CLIENT=ON -DBUILD_VDF_BENCH=ON -DBUILD_VDF_TESTS=ON -DBUILD_HW_TOOLS=OFF + cmake -S src -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_ASM_COMPILER=clang-cl -DBOOST_INCLUDE_DIR="$env:BOOST_INCLUDE_DIR" -DBUILD_PYTHON=OFF -DBUILD_CHIAVDFC=OFF -DBUILD_VDF_CLIENT=ON -DBUILD_VDF_BENCH=ON -DBUILD_VDF_TESTS=ON -DBUILD_HW_TOOLS=OFF cmake --build build --target vdf_client vdf_bench 1weso_test 2weso_test prover_test - - name: Benchmark vdf_bench square (Unix) - if: "!startsWith(matrix.os, 'windows')" - run: | - cd src - echo "Benchmarking vdf_bench with 2,500,000 iterations of square_asm" - ./vdf_bench square_asm 2500000 - - name: Test vdf-client if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') run: | @@ -141,52 +132,12 @@ jobs: $env:CHIAVDF_PROVER_TEST_FAST = "1" .\prover_test.exe - - name: Benchmark vdf-client - if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') - run: | - cd src - echo "Benchmarking vdf_client with 400,000 iterations of vdf_bench" - ./vdf_bench square_asm 400000 - - - name: Benchmark vdf-client (Windows) - if: matrix.config == 'optimized=1' && startsWith(matrix.os, 'windows') - shell: pwsh - run: | - cd build - $dllPaths = @() - if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } - if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } - if ($dllPaths.Count -gt 0) { $env:PATH = ($dllPaths -join ';') + ';' + $env:PATH } - Write-Host "Benchmarking vdf_client with 400,000 iterations of vdf_bench" - & .\vdf_bench.exe square_asm 400000 - Write-Host "vdf_bench exit code: $LASTEXITCODE" - if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } - - - name: Profile vdf_bench square (Windows) - if: matrix.config == 'optimized=1' && startsWith(matrix.os, 'windows') - shell: pwsh - run: | - cd build - $dllPaths = @() - if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } - if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } - if ($dllPaths.Count -gt 0) { $env:PATH = ($dllPaths -join ';') + ';' + $env:PATH } - Write-Host "Profiling vdf_bench square with 200,000 iterations" - & .\vdf_bench.exe square 200000 - - - name: Benchmark vdf_bench square (Unix) + - name: Benchmark vdf_bench square (Linux/Mac) if: "!startsWith(matrix.os, 'windows')" run: | cd src - echo "Benchmarking vdf_bench with 1,000,000 iterations of square_asm" - ./vdf_bench square_asm 1000000 - - - name: Profile vdf_bench square (Unix) - if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') - run: | - cd src - echo "Profiling vdf_bench square with 200,000 iterations" - ./vdf_bench square 200000 + echo "Benchmarking vdf_bench with 2,000,000 iterations of square_asm" + ./vdf_bench square_asm 2000000 - name: Benchmark vdf_bench square (Windows) if: startsWith(matrix.os, 'windows') @@ -197,307 +148,8 @@ jobs: if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } if ($dllPaths.Count -gt 0) { $env:PATH = ($dllPaths -join ';') + ';' + $env:PATH } - Write-Host "Benchmarking vdf_bench with 1,000,000 iterations of square_asm" - & .\vdf_bench.exe square_asm 1000000 + Write-Host "Benchmarking vdf_bench with 2,000,000 iterations of square_asm" + & .\vdf_bench.exe square_asm 2000000 Write-Host "vdf_bench exit code: $LASTEXITCODE" if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } - perf_experiments: - name: Perf experiments ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest] - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Install perf deps (Ubuntu) - if: startsWith(matrix.os, 'ubuntu') - run: | - sudo apt-get update -y -o Acquire::Retries=3 - sudo apt-get install -y clang llvm lld ninja-build libgmp-dev gcc - - - name: Install perf deps (Windows) - if: startsWith(matrix.os, 'windows') - shell: pwsh - run: | - choco install llvm ninja -y - "C:\Program Files\LLVM\bin" | Out-File -Append -FilePath $env:GITHUB_PATH - - - name: Checkout mpir for Windows - if: startsWith(matrix.os, 'windows') - uses: actions/checkout@v6 - with: - repository: Chia-Network/mpir_gc_x64 - fetch-depth: 1 - path: mpir_gc_x64 - - - name: Run perf experiments (Ubuntu) - if: startsWith(matrix.os, 'ubuntu') - run: | - set -euo pipefail - set -x - trap 'echo "perf_experiments ubuntu failed"; find . -maxdepth 3 -type f -name "vdf_bench" -print; find . -maxdepth 3 -type f -name "CMakeCache.txt" -print' ERR - mkdir -p pgo - variants=("baseline" "lto" "march" "lto-march" "pgo" "pgo-march") - baseline_speed="" - - run_bench() { - local build_dir="$1" - local build_log="${build_dir}/build.log" - if ! cmake --build "$build_dir" --target vdf_bench 2>&1 | tee "$build_log" >&2; then - echo "vdf_bench build failed for ${build_dir}" >&2 - cat "$build_log" >&2 - return 1 - fi - local out_file="${build_dir}/bench.out" - local bench_path - bench_path="$(find "${build_dir}" -name vdf_bench -type f -print -quit)" - if [[ -z "${bench_path}" ]]; then - echo "vdf_bench not found under ${build_dir}" >&2 - find "${build_dir}" -maxdepth 3 -type f -print >&2 - return 1 - fi - "${bench_path}" square_asm 1000000 2>&1 | tee "$out_file" >&2 - local speed - speed="$(python -c 'import re,sys,pathlib; text=pathlib.Path(sys.argv[1]).read_text(errors="replace"); m=re.search(r"speed:\s*([0-9]+(?:\.[0-9]+)?)K ips", text); sys.exit("speed not found") if not m else None; print(m.group(1))' "$out_file")" - printf '%s\n' "$speed" - } - - for variant in "${variants[@]}"; do - echo "== perf variant: ${variant} ==" - build_dir="build-perf-${variant}" - cmake_flags=( - -S src - -B "${build_dir}" - -G Ninja - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_C_COMPILER=clang - -DCMAKE_CXX_COMPILER=clang++ - -DCMAKE_ASM_COMPILER=gcc - -DCHIAVDF_DISABLE_PIE=ON - -DBUILD_PYTHON=OFF - -DBUILD_CHIAVDFC=OFF - -DBUILD_VDF_CLIENT=OFF - -DBUILD_VDF_BENCH=ON - -DBUILD_VDF_TESTS=OFF - -DBUILD_HW_TOOLS=OFF - ) - cmake_flags+=(-DCMAKE_POSITION_INDEPENDENT_CODE=OFF) - cmake_flags+=(-DCMAKE_EXE_LINKER_FLAGS=-no-pie) - if [[ "$variant" == *"lto"* ]]; then - cmake_flags+=(-DCHIAVDF_USE_LTO=ON) - fi - if [[ "$variant" == *"march"* ]]; then - cmake_flags+=(-DCHIAVDF_MARCH=x86-64-v3) - fi - - if [[ "$variant" == pgo* ]]; then - gen_dir="${build_dir}-gen" - use_dir="${build_dir}-use" - cmake "${cmake_flags[@]}" -B "${gen_dir}" -DCHIAVDF_PGO_GENERATE=ON - cmake --build "${gen_dir}" --target vdf_bench - gen_bench_path="$(find "${gen_dir}" -name vdf_bench -type f -print -quit)" - if [[ -z "${gen_bench_path}" ]]; then - echo "vdf_bench not found under ${gen_dir}" - find "${gen_dir}" -maxdepth 3 -type f -print - exit 1 - fi - LLVM_PROFILE_FILE="$(pwd)/pgo/${variant}.profraw" "${gen_bench_path}" square_asm 200000 >/dev/null - llvm-profdata merge -output="pgo/${variant}.profdata" "pgo/${variant}.profraw" - cmake "${cmake_flags[@]}" -B "${use_dir}" -DCHIAVDF_PGO_USE="$(pwd)/pgo/${variant}.profdata" - if ! speed=$(run_bench "${use_dir}"); then - echo "run_bench failed for ${use_dir}" - exit 1 - fi - else - cmake "${cmake_flags[@]}" - if ! speed=$(run_bench "${build_dir}"); then - echo "run_bench failed for ${build_dir}" - exit 1 - fi - fi - - if [[ -z "${baseline_speed}" ]]; then - baseline_speed="${speed}" - echo "PERF baseline speed=${speed}K ips" - if [[ "${variant}" == "baseline" ]]; then - hash_out="asm_hashes_ubuntu.txt" - find "${build_dir}" -name '*_asm_compiled.s' -type f -print | sort | while read -r asm_file; do - sha256sum "$asm_file" - done | tee "${hash_out}" - fi - else - delta=$(python -c 'import sys; base=float(sys.argv[1]); cur=float(sys.argv[2]); print(round((cur/base - 1.0) * 100.0, 1))' "${baseline_speed}" "${speed}") - echo "PERF variant=${variant} speed=${speed}K ips baseline=${baseline_speed}K ips delta=${delta}%" - fi - done - - - name: Run perf experiments (Windows) - if: startsWith(matrix.os, 'windows') - shell: pwsh - run: | - $ErrorActionPreference = "Stop" - $dllPaths = @() - if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } - if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } - if ($dllPaths.Count -gt 0) { $env:PATH = ($dllPaths -join ';') + ';' + $env:PATH } - $variants = @( - "baseline", - "lto", - "march", - "lto-march", - "pgo", - "pgo-march", - "clangcl", - "clangcl-lto", - "clangcl-march", - "clangcl-lto-march", - "clangcl-nosec", - "clangcl-lto-nosec", - "lld-lto" - ) - $baselineSpeed = $null - New-Item -ItemType Directory -Force -Path pgo | Out-Null - - function Get-SpeedFromOutput($output) { - $match = $output | Select-String -Pattern "speed:\s*([0-9\.]+)K ips" | Select-Object -First 1 - if (-not $match) { throw "speed not found" } - return [double]$match.Matches[0].Groups[1].Value - } - - function Run-Bench($buildDir) { - cmake --build $buildDir --target vdf_bench | ForEach-Object { Write-Host $_ } - $outPath = "$buildDir\bench.out" - $benchPath = (Get-ChildItem -Path $buildDir -Recurse -Filter vdf_bench.exe | Select-Object -First 1).FullName - if (-not $benchPath) { - Write-Host "vdf_bench.exe not found under $buildDir" - Get-ChildItem -Path $buildDir -Recurse -File | ForEach-Object { $_.FullName } - throw "vdf_bench.exe not found under $buildDir" - } - $out = & $benchPath square_asm 1000000 2>&1 - $outText = [string]::Join("`n", $out) - $outText | Set-Content -Path $outPath - $out | ForEach-Object { Write-Host $_ } - $script:LastBenchPath = $benchPath - try { - return (Get-SpeedFromOutput $outText) - } catch { - Write-Host "Failed to parse speed from $outPath" - $out | ForEach-Object { Write-Host $_ } - throw - } - } - - function Try-Profile($benchPath) { - if (-not $benchPath) { return } - $wpr = Get-Command wpr.exe -ErrorAction SilentlyContinue - if (-not $wpr) { - Write-Host "wpr.exe not found; skipping profile capture" - return - } - $tracePath = Join-Path $env:GITHUB_WORKSPACE "wpr-baseline.etl" - try { - wpr -start CPU | Out-Null - & $benchPath square_asm 200000 | Out-Null - wpr -stop $tracePath | Out-Null - } catch { - Write-Host "wpr capture failed: $_" - try { wpr -cancel | Out-Null } catch { } - } - } - - foreach ($variant in $variants) { - Write-Host "== perf variant: $variant ==" - $buildDir = "build-perf-$variant" - $useClangCl = $variant -like "clangcl*" - $cmakeArgs = @( - "-S", "src", - "-B", $buildDir, - "-G", "Ninja", - "-DCMAKE_BUILD_TYPE=Release", - "-DCMAKE_ASM_COMPILER=clang", - "-DBUILD_PYTHON=OFF", - "-DBUILD_CHIAVDFC=OFF", - "-DBUILD_VDF_CLIENT=OFF", - "-DBUILD_VDF_BENCH=ON", - "-DBUILD_VDF_TESTS=OFF", - "-DBUILD_HW_TOOLS=OFF" - ) - if ($useClangCl) { - $cmakeArgs += "-DCMAKE_C_COMPILER=clang-cl" - $cmakeArgs += "-DCMAKE_CXX_COMPILER=clang-cl" - } else { - $cmakeArgs += "-DCMAKE_C_COMPILER=clang" - $cmakeArgs += "-DCMAKE_CXX_COMPILER=clang++" - } - if ($variant -like "*lto*") { - $cmakeArgs += "-DCHIAVDF_USE_LTO=ON" - } - if ($variant -like "*march*") { - $cmakeArgs += "-DCHIAVDF_MARCH=x86-64-v3" - } - if ($variant -like "*nosec*") { - $cmakeArgs += "-DCHIAVDF_WINDOWS_DISABLE_SECURITY=ON" - } - if ($variant -like "*lld*") { - $cmakeArgs += "-DCHIAVDF_WINDOWS_USE_LLD=ON" - } - - if ($variant -like "pgo*") { - $genDir = "$buildDir-gen" - $useDir = "$buildDir-use" - cmake @cmakeArgs -B $genDir -DCHIAVDF_PGO_GENERATE=ON - cmake --build $genDir --target vdf_bench - $env:LLVM_PROFILE_FILE = "$(Get-Location)\pgo\$variant.profraw" - $genBenchPath = (Get-ChildItem -Path $genDir -Recurse -Filter vdf_bench.exe | Select-Object -First 1).FullName - if (-not $genBenchPath) { throw "vdf_bench.exe not found under $genDir" } - & $genBenchPath square_asm 200000 | Out-Null - & llvm-profdata merge -output "pgo\$variant.profdata" "pgo\$variant.profraw" - cmake @cmakeArgs -B $useDir -DCHIAVDF_PGO_USE="$(Get-Location)\pgo\$variant.profdata" - $speed = [double](Run-Bench $useDir) - } else { - cmake @cmakeArgs - $speed = [double](Run-Bench $buildDir) - } - - if (-not $baselineSpeed) { - $baselineSpeed = [double]$speed - Write-Host ("PERF baseline speed={0}K ips" -f $speed) - $hashOut = Join-Path $env:GITHUB_WORKSPACE "asm_hashes_windows.txt" - Get-ChildItem -Path $buildDir -Recurse -Filter "*_asm_compiled.s" | Sort-Object FullName | ForEach-Object { - $hash = Get-FileHash -Algorithm SHA256 $_.FullName - "{0} {1}" -f $hash.Hash, $hash.Path - } | Tee-Object -FilePath $hashOut | ForEach-Object { Write-Host $_ } - Try-Profile $script:LastBenchPath - } else { - $delta = [math]::Round((($speed / $baselineSpeed) - 1) * 100, 1) - Write-Host ("PERF variant={0} speed={1}K ips baseline={2}K ips delta={3}%" -f $variant, $speed, $baselineSpeed, $delta) - } - } - - - name: Upload asm hashes (Ubuntu) - if: startsWith(matrix.os, 'ubuntu') - uses: actions/upload-artifact@v4 - with: - name: asm-hashes-ubuntu - path: asm_hashes_ubuntu.txt - if-no-files-found: ignore - - - name: Upload asm hashes (Windows) - if: startsWith(matrix.os, 'windows') - uses: actions/upload-artifact@v4 - with: - name: asm-hashes-windows - path: asm_hashes_windows.txt - if-no-files-found: ignore - - - name: Upload Windows perf trace - if: startsWith(matrix.os, 'windows') - uses: actions/upload-artifact@v4 - with: - name: windows-perf-trace - path: wpr-baseline.etl - if-no-files-found: ignore From 71121ab6bd1c46c30c9c5b699333a8b5aafc0122 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Sat, 7 Feb 2026 15:25:13 -0800 Subject: [PATCH 05/78] build: remove perf-only CMake toggles --- src/CMakeLists.txt | 65 +++++++++++----------------------------------- 1 file changed, 15 insertions(+), 50 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9da7c348..dd021f01 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,13 +7,6 @@ option(BUILD_VDF_TESTS "Build vdf test binaries (1weso/2weso/prover)" OFF) option(BUILD_HW_TOOLS "Build hardware timelord tools" OFF) option(ENABLE_GNU_ASM "Enable GNU-style asm pipeline on x86/x64" ON) option(HARDENING "Enable hardening" OFF) -option(CHIAVDF_USE_LTO "Enable LTO for perf experiments" OFF) -option(CHIAVDF_PGO_GENERATE "Enable PGO generate instrumentation" OFF) -set(CHIAVDF_PGO_USE "" CACHE STRING "Path to PGO profdata for use") -set(CHIAVDF_MARCH "" CACHE STRING "Override -march for perf experiments") -option(CHIAVDF_DISABLE_PIE "Disable PIE for perf experiments" OFF) -option(CHIAVDF_WINDOWS_DISABLE_SECURITY "Disable Windows security mitigations for perf experiments" OFF) -option(CHIAVDF_WINDOWS_USE_LLD "Use lld-link on Windows for perf experiments" OFF) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -36,6 +29,7 @@ if(MSVC) # MSVC does not provide the GNU intrinsics headers used by compile_asm. set(ENABLE_GNU_ASM OFF CACHE BOOL "Enable GNU-style asm pipeline on x86/x64" FORCE) endif() + # clang-cl defaults to the MSVC linker (preferred for perf and compatibility). else() add_compile_options("$<$:-Og>") endif() @@ -232,51 +226,24 @@ endfunction() function(vdf_add_windows_clang_opts target_name) if(WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - target_compile_options( - ${target_name} - PRIVATE - "$<$:-O3>" - "$<$:-ffp-contract=fast>" - "$<$:-fno-math-errno>" - ) - endif() -endfunction() - -function(vdf_add_perf_opts target_name) - if(CHIAVDF_USE_LTO) - set_property(TARGET ${target_name} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) - endif() - if(CHIAVDF_DISABLE_PIE) - target_compile_options(${target_name} PRIVATE "$<$:-fno-pie>") - target_link_options(${target_name} PRIVATE -no-pie) - endif() - if(CHIAVDF_MARCH) if(MSVC) - target_compile_options(${target_name} PRIVATE "$<$:/clang:-march=${CHIAVDF_MARCH}>") - else() - target_compile_options(${target_name} PRIVATE "$<$:-march=${CHIAVDF_MARCH}>") - endif() - endif() - if(CHIAVDF_PGO_GENERATE) - target_compile_options(${target_name} PRIVATE "$<$:-fprofile-instr-generate>") - target_link_options(${target_name} PRIVATE -fprofile-instr-generate) - endif() - if(CHIAVDF_PGO_USE) - target_compile_options(${target_name} PRIVATE "$<$:-fprofile-instr-use=${CHIAVDF_PGO_USE}>") - target_link_options(${target_name} PRIVATE "-fprofile-instr-use=${CHIAVDF_PGO_USE}") - endif() - if(WIN32 AND CHIAVDF_WINDOWS_DISABLE_SECURITY) - if(MSVC) - target_compile_options(${target_name} PRIVATE /GS-) - target_link_options(${target_name} PRIVATE "LINKER:/guard:cf-") + target_compile_options( + ${target_name} + PRIVATE + "$<$:/O2>" + "$<$:/fp:fast>" + "$<$:/clang:-fno-math-errno>" + ) else() - target_compile_options(${target_name} PRIVATE "$<$:-fno-stack-protector>") - target_link_options(${target_name} PRIVATE "-Wl,/guard:cf-") + target_compile_options( + ${target_name} + PRIVATE + "$<$:-O3>" + "$<$:-ffp-contract=fast>" + "$<$:-fno-math-errno>" + ) endif() endif() - if(WIN32 AND CHIAVDF_WINDOWS_USE_LLD AND NOT MSVC) - target_link_options(${target_name} PRIVATE -fuse-ld=lld) - endif() endfunction() if(BUILD_VDF_CLIENT) @@ -292,7 +259,6 @@ if(BUILD_VDF_CLIENT) target_link_libraries(vdf_client PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) vdf_add_windows_asm_linker_flags(vdf_client) vdf_add_windows_clang_opts(vdf_client) - vdf_add_perf_opts(vdf_client) endif() if(BUILD_VDF_BENCH) @@ -304,7 +270,6 @@ if(BUILD_VDF_BENCH) target_link_libraries(vdf_bench PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) vdf_add_windows_asm_linker_flags(vdf_bench) vdf_add_windows_clang_opts(vdf_bench) - vdf_add_perf_opts(vdf_bench) endif() if(BUILD_VDF_TESTS) From 679a3875fdf5084491f0ab7cd6ed30b0680eb955 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Sat, 7 Feb 2026 15:25:31 -0800 Subject: [PATCH 06/78] core: gate AVX logging behind env flag --- src/parameters.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/parameters.h b/src/parameters.h index 4b5160a8..8d0059d7 100644 --- a/src/parameters.h +++ b/src/parameters.h @@ -31,6 +31,7 @@ extern bool enable_all_instructions; #include #include +#include #include inline std::atomic bAVX2{false}; @@ -51,6 +52,10 @@ inline bool env_flag(const char* name) { return true; } +inline bool should_log_avx() { + return env_flag("CHIAVDF_LOG_AVX"); +} + #if defined(__i386) || defined(_M_IX86) #define ARCH_X86 #elif defined(__x86_64__) || defined(_M_X64) @@ -107,6 +112,9 @@ inline void init_avx_flags() } else { bAVX2.store(avx2bit && adxbit, std::memory_order_relaxed); } + if (bAVX2.load(std::memory_order_relaxed) && should_log_avx()) { + std::fprintf(stderr, "AVX2 enabled (avx2=%d adx=%d)\n", avx2bit ? 1 : 0, adxbit ? 1 : 0); + } if (disable_avx512) { enable_avx512_ifma.store(false, std::memory_order_relaxed); @@ -117,6 +125,9 @@ inline void init_avx_flags() } else { enable_avx512_ifma.store(false, std::memory_order_relaxed); } + if (enable_avx512_ifma.load(std::memory_order_relaxed) && should_log_avx()) { + std::fprintf(stderr, "AVX512 IFMA enabled (f=%d ifma=%d)\n", avx512fbit ? 1 : 0, avx512ifmabit ? 1 : 0); + } #elif defined(ARCH_ARM) bAVX2.store(false, std::memory_order_relaxed); enable_avx512_ifma.store(false, std::memory_order_relaxed); From 70c50acbf38003a40970c68c3e631b2191877d1d Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Sat, 7 Feb 2026 15:25:40 -0800 Subject: [PATCH 07/78] asm: document Windows ABI restore --- src/asm_vm.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/asm_vm.h b/src/asm_vm.h index b3bad099..aba80542 100644 --- a/src/asm_vm.h +++ b/src/asm_vm.h @@ -166,6 +166,7 @@ struct asm_function { //this takes 4 cycles including ret, if there is nothing else to do if (d_align_stack) { #ifdef CHIA_WINDOWS + // Windows ABI: restore YMM6–YMM15 from the stack area reserved during prologue. const int windows_saved_rsp_bytes = 8; const int windows_shadow_space_bytes = 0x20; const int windows_xmm_save_base = windows_saved_rsp_bytes + spill_bytes + windows_shadow_space_bytes; From e89c8051193c60ff888146bc22d7fc304101a67c Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Sat, 7 Feb 2026 15:25:57 -0800 Subject: [PATCH 08/78] docs: remove Windows perf notes --- WINDOWS_PERF_NOTES.md | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 WINDOWS_PERF_NOTES.md diff --git a/WINDOWS_PERF_NOTES.md b/WINDOWS_PERF_NOTES.md deleted file mode 100644 index 643742ef..00000000 --- a/WINDOWS_PERF_NOTES.md +++ /dev/null @@ -1,25 +0,0 @@ -# Windows perf notes (vdf_bench square_asm) - -## Summary -- Ubuntu baseline: ~160.3K ips -- Windows baseline: ~128.3K ips -- Gap: ~20% slower on Windows in current clang++ GNU-style asm build - -## Ubuntu perf experiment deltas -- lto: -0.7% -- march: -2.1% -- lto-march: 0.0% -- pgo: -0.5% -- pgo-march: -0.9% - -## Windows perf experiment deltas -- lto: -10.4% -- march: +0.4% -- lto-march: +0.9% -- pgo: +1.3% -- pgo-march: -4.1% - -## Next investigation hooks (in CI) -- Baseline asm hashes are captured for Ubuntu/Windows to compare generated `.s`. -- Optional Windows WPR trace (`wpr-baseline.etl`) is captured when available. -- Additional Windows variants (clang-cl, lld-link, nosec) are available for parity testing. From 980b6974cf8a7d65e31122a49393c3a7fb50b220 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Sat, 7 Feb 2026 15:39:26 -0800 Subject: [PATCH 09/78] Nit note in README and clean up some language in test.yaml --- .github/workflows/test.yaml | 6 +++--- README.md | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 0d8393ca..7ab05c71 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -77,7 +77,7 @@ jobs: cmake -S src -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_ASM_COMPILER=clang-cl -DBOOST_INCLUDE_DIR="$env:BOOST_INCLUDE_DIR" -DBUILD_PYTHON=OFF -DBUILD_CHIAVDFC=OFF -DBUILD_VDF_CLIENT=ON -DBUILD_VDF_BENCH=ON -DBUILD_VDF_TESTS=ON -DBUILD_HW_TOOLS=OFF cmake --build build --target vdf_client vdf_bench 1weso_test 2weso_test prover_test - - name: Test vdf-client + - name: Run vdf tests (short) (Windows) if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') run: | cd src @@ -92,7 +92,7 @@ jobs: CHIAVDF_PROVER_TEST_FAST=1 ./prover_test fi - - name: Test vdf-client + - name: Run vdf tests (short) if: matrix.config != 'optimized=1' && !startsWith(matrix.os, 'windows') run: | cd src @@ -132,7 +132,7 @@ jobs: $env:CHIAVDF_PROVER_TEST_FAST = "1" .\prover_test.exe - - name: Benchmark vdf_bench square (Linux/Mac) + - name: Benchmark vdf_bench square (Ubuntu/Mac) if: "!startsWith(matrix.os, 'windows')" run: | cd src diff --git a/README.md b/README.md index 537cd261..1f65c04d 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ to it by the Timelord. The repo also includes a benchmarking tool to get a sense of the iterations per second of a given CPU called vdf_bench. Try `./vdf_bench square_asm 250000` for an ips estimate on x86/x64 (phased/asm pipeline). On non-x86 architectures, use `./vdf_bench square 250000` (NUDUPL). +Set `CHIAVDF_LOG_AVX=1` to emit AVX feature detection logs during startup. To build vdf_client set the environment variable BUILD_VDF_CLIENT to "Y". `export BUILD_VDF_CLIENT=Y`. From d04e5fbbab25af0499f2b61017233ac8da6b0122 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Sat, 7 Feb 2026 15:49:16 -0800 Subject: [PATCH 10/78] Fix step name --- .github/workflows/test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 7ab05c71..df64315b 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -77,7 +77,7 @@ jobs: cmake -S src -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_ASM_COMPILER=clang-cl -DBOOST_INCLUDE_DIR="$env:BOOST_INCLUDE_DIR" -DBUILD_PYTHON=OFF -DBUILD_CHIAVDFC=OFF -DBUILD_VDF_CLIENT=ON -DBUILD_VDF_BENCH=ON -DBUILD_VDF_TESTS=ON -DBUILD_HW_TOOLS=OFF cmake --build build --target vdf_client vdf_bench 1weso_test 2weso_test prover_test - - name: Run vdf tests (short) (Windows) + - name: Run vdf tests (optimized) if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') run: | cd src From ad87252c947c371d913e3346b3e37a62d776dc04 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Mon, 9 Feb 2026 12:53:07 -0800 Subject: [PATCH 11/78] various workflow clean ups and fix AVX512 flag --- .github/workflows/test.yaml | 32 +++++++++++++++++++++++--------- src/asm_base.h | 4 +++- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index df64315b..541e221f 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -74,7 +74,16 @@ jobs: if: startsWith(matrix.os, 'windows') shell: pwsh run: | - cmake -S src -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_ASM_COMPILER=clang-cl -DBOOST_INCLUDE_DIR="$env:BOOST_INCLUDE_DIR" -DBUILD_PYTHON=OFF -DBUILD_CHIAVDFC=OFF -DBUILD_VDF_CLIENT=ON -DBUILD_VDF_BENCH=ON -DBUILD_VDF_TESTS=ON -DBUILD_HW_TOOLS=OFF + $cmakeBuildType = "Release" + $sanitizerFlags = "" + if ("${{ matrix.config }}" -eq "ASAN=1") { + $cmakeBuildType = "RelWithDebInfo" + $sanitizerFlags = "-fsanitize=address" + } elseif ("${{ matrix.config }}" -eq "TSAN=1") { + $cmakeBuildType = "RelWithDebInfo" + $sanitizerFlags = "-fsanitize=thread" + } + cmake -S src -B build -G Ninja -DCMAKE_BUILD_TYPE=$cmakeBuildType -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_ASM_COMPILER=clang-cl -DCMAKE_C_FLAGS="$sanitizerFlags" -DCMAKE_CXX_FLAGS="$sanitizerFlags" -DCMAKE_EXE_LINKER_FLAGS="$sanitizerFlags" -DBOOST_INCLUDE_DIR="$env:BOOST_INCLUDE_DIR" -DBUILD_PYTHON=OFF -DBUILD_CHIAVDFC=OFF -DBUILD_VDF_CLIENT=ON -DBUILD_VDF_BENCH=ON -DBUILD_VDF_TESTS=ON -DBUILD_HW_TOOLS=OFF cmake --build build --target vdf_client vdf_bench 1weso_test 2weso_test prover_test - name: Run vdf tests (optimized) @@ -124,23 +133,28 @@ jobs: if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } if ($dllPaths.Count -gt 0) { $env:PATH = ($dllPaths -join ';') + ';' + $env:PATH } - Write-Host "Running 1weso_test" - .\1weso_test.exe - Write-Host "Running 2weso_test" - .\2weso_test.exe - Write-Host "Running prover_test" + function Invoke-TestExe([string]$name, [string[]]$args = @()) { + Write-Host "Running $name" + & ".\$name.exe" @args + if ($LASTEXITCODE -ne 0) { + Write-Host "$name exit code: $LASTEXITCODE" + exit $LASTEXITCODE + } + } + Invoke-TestExe "1weso_test" + Invoke-TestExe "2weso_test" $env:CHIAVDF_PROVER_TEST_FAST = "1" - .\prover_test.exe + Invoke-TestExe "prover_test" - name: Benchmark vdf_bench square (Ubuntu/Mac) - if: "!startsWith(matrix.os, 'windows')" + if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') run: | cd src echo "Benchmarking vdf_bench with 2,000,000 iterations of square_asm" ./vdf_bench square_asm 2000000 - name: Benchmark vdf_bench square (Windows) - if: startsWith(matrix.os, 'windows') + if: matrix.config == 'optimized=1' && startsWith(matrix.os, 'windows') shell: pwsh run: | cd build diff --git a/src/asm_base.h b/src/asm_base.h index 80e42720..9621fd78 100644 --- a/src/asm_base.h +++ b/src/asm_base.h @@ -140,7 +140,9 @@ string constant_address_avx512_uint64(array value, bool use_brackets= if (name.empty()) { name=m.alloc_label(); -#if defined(CHIAOSX) || defined(CHIA_WINDOWS) +#if defined(CHIA_WINDOWS) + APPEND_M(str( ".section .rdata,\"dr\"" )); +#elif defined(CHIAOSX) APPEND_M(str( ".text " )); #else APPEND_M(str( ".text 1" )); From 5a7ee42d8ece28e674e62f71857423e00012a53b Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Mon, 9 Feb 2026 13:06:45 -0800 Subject: [PATCH 12/78] fix windows runners in test.yaml --- .github/workflows/test.yaml | 41 ++++- README.md | 29 +++ src/vdf_base_integer.cpp | 341 ++++++++++++++++++++++++++++++++++++ 3 files changed, 407 insertions(+), 4 deletions(-) create mode 100644 src/vdf_base_integer.cpp diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 541e221f..9275d102 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -75,15 +75,48 @@ jobs: shell: pwsh run: | $cmakeBuildType = "Release" - $sanitizerFlags = "" + $cmakeCFlags = "" + $cmakeCxxFlags = "" + $cmakeExeLinkerFlags = "" + $cmakeSharedLinkerFlags = "" + $cmakeModuleLinkerFlags = "" + # Force compiler probes (try_compile) to use release CRT when + # sanitizers are enabled; clang-cl rejects /MDd + -fsanitize=address. + $cmakeTryCompileConfig = "Release" if ("${{ matrix.config }}" -eq "ASAN=1") { $cmakeBuildType = "RelWithDebInfo" - $sanitizerFlags = "-fsanitize=address" + $cmakeCFlags = "-fsanitize=address" + $cmakeCxxFlags = "-fsanitize=address" + $cmakeExeLinkerFlags = "-fsanitize=address" + $cmakeSharedLinkerFlags = "-fsanitize=address" + $cmakeModuleLinkerFlags = "-fsanitize=address" } elseif ("${{ matrix.config }}" -eq "TSAN=1") { $cmakeBuildType = "RelWithDebInfo" - $sanitizerFlags = "-fsanitize=thread" + $cmakeCFlags = "-fsanitize=thread" + $cmakeCxxFlags = "-fsanitize=thread" + $cmakeExeLinkerFlags = "-fsanitize=thread" + $cmakeSharedLinkerFlags = "-fsanitize=thread" + $cmakeModuleLinkerFlags = "-fsanitize=thread" } - cmake -S src -B build -G Ninja -DCMAKE_BUILD_TYPE=$cmakeBuildType -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_ASM_COMPILER=clang-cl -DCMAKE_C_FLAGS="$sanitizerFlags" -DCMAKE_CXX_FLAGS="$sanitizerFlags" -DCMAKE_EXE_LINKER_FLAGS="$sanitizerFlags" -DBOOST_INCLUDE_DIR="$env:BOOST_INCLUDE_DIR" -DBUILD_PYTHON=OFF -DBUILD_CHIAVDFC=OFF -DBUILD_VDF_CLIENT=ON -DBUILD_VDF_BENCH=ON -DBUILD_VDF_TESTS=ON -DBUILD_HW_TOOLS=OFF + cmake -S src -B build -G Ninja ` + -DCMAKE_BUILD_TYPE=$cmakeBuildType ` + -DCMAKE_TRY_COMPILE_CONFIGURATION=$cmakeTryCompileConfig ` + -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL ` + -DCMAKE_C_COMPILER=clang-cl ` + -DCMAKE_CXX_COMPILER=clang-cl ` + -DCMAKE_ASM_COMPILER=clang-cl ` + -DCMAKE_C_FLAGS="$cmakeCFlags" ` + -DCMAKE_CXX_FLAGS="$cmakeCxxFlags" ` + -DCMAKE_EXE_LINKER_FLAGS="$cmakeExeLinkerFlags" ` + -DCMAKE_SHARED_LINKER_FLAGS="$cmakeSharedLinkerFlags" ` + -DCMAKE_MODULE_LINKER_FLAGS="$cmakeModuleLinkerFlags" ` + -DBOOST_INCLUDE_DIR="$env:BOOST_INCLUDE_DIR" ` + -DBUILD_PYTHON=OFF ` + -DBUILD_CHIAVDFC=OFF ` + -DBUILD_VDF_CLIENT=ON ` + -DBUILD_VDF_BENCH=ON ` + -DBUILD_VDF_TESTS=ON ` + -DBUILD_HW_TOOLS=OFF cmake --build build --target vdf_client vdf_bench 1weso_test 2weso_test prover_test - name: Run vdf tests (optimized) diff --git a/README.md b/README.md index 1f65c04d..b0d59fa5 100644 --- a/README.md +++ b/README.md @@ -40,12 +40,41 @@ sense of the iterations per second of a given CPU called vdf_bench. Try pipeline). On non-x86 architectures, use `./vdf_bench square 250000` (NUDUPL). Set `CHIAVDF_LOG_AVX=1` to emit AVX feature detection logs during startup. +For direct CMake builds, the following options are available: + +- `BUILD_VDF_CLIENT` - build `vdf_client` +- `BUILD_VDF_BENCH` - build `vdf_bench` +- `BUILD_VDF_TESTS` - build `1weso_test`, `2weso_test`, and `prover_test` +- `BUILD_HW_TOOLS` - build hardware timelord tools +- `ENABLE_GNU_ASM` - enable GNU-style asm pipeline on x86/x64 (enabled by default) + +Example: + +```bash +cmake -S src -B build \ + -DBUILD_PYTHON=OFF \ + -DBUILD_CHIAVDFC=OFF \ + -DBUILD_VDF_CLIENT=ON \ + -DBUILD_VDF_BENCH=ON \ + -DBUILD_VDF_TESTS=ON +cmake --build build --target vdf_client vdf_bench 1weso_test 2weso_test prover_test +``` + To build vdf_client set the environment variable BUILD_VDF_CLIENT to "Y". `export BUILD_VDF_CLIENT=Y`. Similarly, to build vdf_bench set the environment variable BUILD_VDF_BENCH to "Y". `export BUILD_VDF_BENCH=Y`. +AVX runtime flags: + +- `CHIAVDF_LOG_AVX=1`: emit AVX detection logs at startup +- `CHIA_DISABLE_AVX2=1`: disable AVX2 path even when supported +- `CHIA_FORCE_AVX2=1`: force AVX2 path +- `CHIA_DISABLE_AVX512_IFMA=1`: disable AVX-512 IFMA path +- `CHIA_ENABLE_AVX512_IFMA=1`: enable AVX-512 IFMA path when CPUID support is present +- `CHIA_FORCE_AVX512_IFMA=1`: force AVX-512 IFMA path + This is currently automated via pip in the [install-timelord.sh](https://github.com/Chia-Network/chia-blockchain/blob/master/install-timelord.sh) script in the diff --git a/src/vdf_base_integer.cpp b/src/vdf_base_integer.cpp new file mode 100644 index 00000000..bd5e21ec --- /dev/null +++ b/src/vdf_base_integer.cpp @@ -0,0 +1,341 @@ +#include "vdf_base.hpp" + +#include + +#include "picosha2.h" +#include "proof_common.h" +#include "primetest.h" + +#include + +static void normalize_form(integer& a, integer& b, integer& c) { + integer r = (a - b) / (a << 1); + integer A = a; + integer B = b + ((r * a) << 1); + integer C = a * r * r + b * r + c; + a = A; + b = B; + c = C; +} + +static void reduce_form_impl(integer& a, integer& b, integer& c) { + integer s = (c + b) / (c << 1); + integer A = c; + integer B = ((s * c) << 1) - b; + integer C = c * s * s - b * s + a; + a = A; + b = B; + c = C; +} + +void reduce_form(integer& a, integer& b, integer& c) { + normalize_form(a, b, c); + while (a > c || (a == c && b < 0)) { + reduce_form_impl(a, b, c); + } + normalize_form(a, b, c); +} + +integer::integer(const string& s) { + mpz_init(impl); + int res = mpz_set_str(impl, s.c_str(), 0); + assert(res == 0); + (void)res; +} + +integer::integer(const std::vector v) { + mpz_init(impl); + mpz_import(impl, v.size(), 1, sizeof(v[0]), 1, 0, &v[0]); +} + +integer::integer(const vector& data) { + mpz_init(impl); + mpz_import(impl, data.size(), -1, 8, 0, 0, &data[0]); +} + +integer::integer(const uint8_t *bytes, size_t size) { + mpz_init(impl); + mpz_import(impl, size, 1, 1, 1, 0, bytes); +} + +vector integer::to_vector() const { + vector res; + res.resize(mpz_sizeinbase(impl, 2) / 64 + 1, 0); + + size_t count = 0; + mpz_export(res.data(), &count, -1, 8, 0, 0, impl); + res.resize(count); + + return res; +} + +vector integer::to_bytes() const { + vector res((mpz_sizeinbase(impl, 2) + 7) / 8); + mpz_export(res.data(), nullptr, 1, 1, 0, 0, impl); + return res; +} + +integer& integer::operator=(int64 i) { + mpz_set_si(impl, i); + return *this; +} + +integer& integer::operator=(const string& s) { + int res = mpz_set_str(impl, s.c_str(), 0); + assert(res == 0); + (void)res; + return *this; +} + +void integer::set_bit(int index, bool value) { + if (value) { + mpz_setbit(impl, index); + } else { + mpz_clrbit(impl, index); + } +} + +bool integer::get_bit(int index) { + return mpz_tstbit(impl, index); +} + +string integer::to_string() const { + string res_string = "0x"; + res_string.resize(res_string.size() + mpz_sizeinbase(impl, 16) + 2); + + mpz_get_str(&(res_string[2]), 16, impl); + + if (res_string.substr(0, 3) == "0x-") { + res_string.at(0) = '-'; + res_string.at(1) = '0'; + res_string.at(2) = 'x'; + } + + return res_string.c_str(); +} + +string integer::to_string_dec() const { + string res_string; + // mpz_sizeinbase() excludes sign; reserve extra for '-' and trailing '\0'. + res_string.resize(mpz_sizeinbase(impl, 10) + 2); + mpz_get_str(&(res_string[0]), 10, impl); + return res_string.c_str(); +} + +integer& integer::operator+=(const integer& t) { + mpz_add(impl, impl, t.impl); + return *this; +} + +integer integer::operator+(const integer& t) const { + integer res; + mpz_add(res.impl, impl, t.impl); + return res; +} + +integer& integer::operator-=(const integer& t) { + mpz_sub(impl, impl, t.impl); + return *this; +} + +integer integer::operator-(const integer& t) const { + integer res; + mpz_sub(res.impl, impl, t.impl); + return res; +} + +integer& integer::operator*=(const integer& t) { + mpz_mul(impl, impl, t.impl); + return *this; +} + +integer integer::operator*(const integer& t) const { + integer res; + mpz_mul(res.impl, impl, t.impl); + return res; +} + +integer& integer::operator<<=(int i) { + assert(i >= 0); + mpz_mul_2exp(impl, impl, i); + return *this; +} + +integer integer::operator<<(int i) const { + assert(i >= 0); + integer res; + mpz_mul_2exp(res.impl, impl, i); + return res; +} + +integer integer::operator-() const { + integer res; + mpz_neg(res.impl, impl); + return res; +} + +integer& integer::operator/=(const integer& t) { + mpz_fdiv_q(impl, impl, t.impl); + return *this; +} + +integer integer::operator/(const integer& t) const { + integer res; + mpz_fdiv_q(res.impl, impl, t.impl); + return res; +} + +integer& integer::operator>>=(int i) { + assert(i >= 0); + mpz_fdiv_q_2exp(impl, impl, i); + return *this; +} + +integer integer::operator>>(int i) const { + assert(i >= 0); + integer res; + mpz_fdiv_q_2exp(res.impl, impl, i); + return res; +} + +integer& integer::operator%=(const integer& t) { + mpz_mod(impl, impl, t.impl); + return *this; +} + +integer integer::operator%(const integer& t) const { + integer res; + mpz_mod(res.impl, impl, t.impl); + return res; +} + +integer integer::fdiv_r(const integer& t) const { + integer res; + mpz_fdiv_r(res.impl, impl, t.impl); + return res; +} + +bool integer::prime() const { + return is_prime_bpsw(impl) != 0; +} + +bool integer::operator<(const integer& t) const { + return mpz_cmp(impl, t.impl) < 0; +} + +bool integer::operator<=(const integer& t) const { + return mpz_cmp(impl, t.impl) <= 0; +} + +bool integer::operator==(const integer& t) const { + return mpz_cmp(impl, t.impl) == 0; +} + +bool integer::operator>=(const integer& t) const { + return mpz_cmp(impl, t.impl) >= 0; +} + +bool integer::operator>(const integer& t) const { + return mpz_cmp(impl, t.impl) > 0; +} + +bool integer::operator!=(const integer& t) const { + return mpz_cmp(impl, t.impl) != 0; +} + +bool integer::operator<(int i) const { + return mpz_cmp_si(impl, i) < 0; +} + +bool integer::operator<=(int i) const { + return mpz_cmp_si(impl, i) <= 0; +} + +bool integer::operator==(int i) const { + return mpz_cmp_si(impl, i) == 0; +} + +bool integer::operator>=(int i) const { + return mpz_cmp_si(impl, i) >= 0; +} + +bool integer::operator>(int i) const { + return mpz_cmp_si(impl, i) > 0; +} + +bool integer::operator!=(int i) const { + return mpz_cmp_si(impl, i) != 0; +} + +int integer::num_bits() const { + return mpz_sizeinbase(impl, 2); +} + +form form::from_abd(const integer& t_a, const integer& t_b, const integer& d) { + form res; + res.a = t_a; + res.b = t_b; + res.c = (t_b * t_b - d); + + if (t_a <= integer(0)) { + throw std::runtime_error("Invalid form. Positive a"); + } + if (res.c % (t_a << 2) != integer(0)) { + throw std::runtime_error("Invalid form. Can't find c."); + } + + res.c /= (t_a << 2); + res.reduce(); + return res; +} + +form form::identity(const integer& d) { + return from_abd(integer(1), integer(1), d); +} + +void form::reduce() { + reduce_form(a, b, c); +} + +bool form::is_reduced() { + int a_cmp_c = mpz_cmp(a.impl, c.impl); + if (a_cmp_c < 0 || (a_cmp_c == 0 && mpz_sgn(b.impl) >= 0)) { + if (mpz_cmpabs(a.impl, b.impl) > 0 || mpz_cmp(a.impl, b.impl) == 0) { + return true; + } + } + return false; +} + +form form::inverse() const { + form res = *this; + res.b = -res.b; + res.reduce(); + return res; +} + +void form::assert_valid(const integer& d) { + assert(check_valid(d)); +} + +bool form::operator==(const form& f) const { + return a == f.a && b == f.b && c == f.c; +} + +bool form::operator<(const form& f) const { + return std::make_tuple(a, b, c) < std::make_tuple(f.a, f.b, f.c); +} + +int form::hash() const { + uint64 res = c.to_vector()[0]; + return int((res >> 4) & ((1ull << 31) - 1)); +} + +uint64_t Prover::GetBlock(uint64_t i, uint64_t k, uint64_t T, integer& B) +{ + integer res = FastPow(2, T - k * (i + 1), B); + mpz_mul_2exp(res.impl, res.impl, k); + res = res / B; + auto res_vector = res.to_vector(); + return res_vector.empty() ? 0 : res_vector[0]; +} From 880d11fec9b9251a7a91912b5b14eac22b48707e Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Mon, 9 Feb 2026 13:16:16 -0800 Subject: [PATCH 13/78] more cmake instruction issues --- .github/workflows/test.yaml | 48 ++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 9275d102..6c9245a2 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -80,9 +80,6 @@ jobs: $cmakeExeLinkerFlags = "" $cmakeSharedLinkerFlags = "" $cmakeModuleLinkerFlags = "" - # Force compiler probes (try_compile) to use release CRT when - # sanitizers are enabled; clang-cl rejects /MDd + -fsanitize=address. - $cmakeTryCompileConfig = "Release" if ("${{ matrix.config }}" -eq "ASAN=1") { $cmakeBuildType = "RelWithDebInfo" $cmakeCFlags = "-fsanitize=address" @@ -98,25 +95,32 @@ jobs: $cmakeSharedLinkerFlags = "-fsanitize=thread" $cmakeModuleLinkerFlags = "-fsanitize=thread" } - cmake -S src -B build -G Ninja ` - -DCMAKE_BUILD_TYPE=$cmakeBuildType ` - -DCMAKE_TRY_COMPILE_CONFIGURATION=$cmakeTryCompileConfig ` - -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL ` - -DCMAKE_C_COMPILER=clang-cl ` - -DCMAKE_CXX_COMPILER=clang-cl ` - -DCMAKE_ASM_COMPILER=clang-cl ` - -DCMAKE_C_FLAGS="$cmakeCFlags" ` - -DCMAKE_CXX_FLAGS="$cmakeCxxFlags" ` - -DCMAKE_EXE_LINKER_FLAGS="$cmakeExeLinkerFlags" ` - -DCMAKE_SHARED_LINKER_FLAGS="$cmakeSharedLinkerFlags" ` - -DCMAKE_MODULE_LINKER_FLAGS="$cmakeModuleLinkerFlags" ` - -DBOOST_INCLUDE_DIR="$env:BOOST_INCLUDE_DIR" ` - -DBUILD_PYTHON=OFF ` - -DBUILD_CHIAVDFC=OFF ` - -DBUILD_VDF_CLIENT=ON ` - -DBUILD_VDF_BENCH=ON ` - -DBUILD_VDF_TESTS=ON ` - -DBUILD_HW_TOOLS=OFF + # Force compiler probes (try_compile) to use release CRT when + # sanitizers are enabled; clang-cl rejects /MDd + -fsanitize=address. + $cmakeArgs = @( + "-S", "src", + "-B", "build", + "-G", "Ninja", + "-DCMAKE_BUILD_TYPE=$cmakeBuildType", + "-DCMAKE_TRY_COMPILE_CONFIGURATION=Release", + "-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL", + "-DCMAKE_C_COMPILER=clang-cl", + "-DCMAKE_CXX_COMPILER=clang-cl", + "-DCMAKE_ASM_COMPILER=clang-cl", + "-DCMAKE_C_FLAGS=$cmakeCFlags", + "-DCMAKE_CXX_FLAGS=$cmakeCxxFlags", + "-DCMAKE_EXE_LINKER_FLAGS=$cmakeExeLinkerFlags", + "-DCMAKE_SHARED_LINKER_FLAGS=$cmakeSharedLinkerFlags", + "-DCMAKE_MODULE_LINKER_FLAGS=$cmakeModuleLinkerFlags", + "-DBOOST_INCLUDE_DIR=$env:BOOST_INCLUDE_DIR", + "-DBUILD_PYTHON=OFF", + "-DBUILD_CHIAVDFC=OFF", + "-DBUILD_VDF_CLIENT=ON", + "-DBUILD_VDF_BENCH=ON", + "-DBUILD_VDF_TESTS=ON", + "-DBUILD_HW_TOOLS=OFF" + ) + & cmake @cmakeArgs cmake --build build --target vdf_client vdf_bench 1weso_test 2weso_test prover_test - name: Run vdf tests (optimized) From f3a5229057fa70b042e7630426a6fe2fba035fd1 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Mon, 9 Feb 2026 13:20:31 -0800 Subject: [PATCH 14/78] harden finding boost on Mac intel --- .github/workflows/test.yaml | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 6c9245a2..9151bf51 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -45,9 +45,27 @@ jobs: - name: Build vdf-client on Mac if: startsWith(matrix.os, 'mac') run: | - brew --prefix --installed boost >/dev/null 2>&1 || brew install boost + brew ls --versions boost >/dev/null 2>&1 || brew install boost + BOOST_VERSION="$(brew list --versions boost | awk '{print $2}')" + BOOST_INCLUDE="" + for cand in \ + "$(brew --prefix boost)/include" \ + "$(brew --prefix)/include" \ + "$(brew --cellar boost)/${BOOST_VERSION}/include"; do + if [ -f "$cand/boost/asio.hpp" ]; then + BOOST_INCLUDE="$cand" + break + fi + done + if [ -z "$BOOST_INCLUDE" ]; then + echo "Could not locate boost/asio.hpp for brew boost=${BOOST_VERSION}" >&2 + brew --prefix boost || true + brew --cellar boost || true + brew info boost || true + exit 1 + fi cd src - make ${{ matrix.config }} -f Makefile.vdf-client + make ${{ matrix.config }} CPPFLAGS="-I${BOOST_INCLUDE} ${CPPFLAGS:-}" -f Makefile.vdf-client - name: Install LLVM and Ninja on Windows if: startsWith(matrix.os, 'windows') From d713c5ea89b79baac2590c3df8874429d4bee719 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Mon, 9 Feb 2026 13:24:45 -0800 Subject: [PATCH 15/78] now cmake isn't always there... --- .github/workflows/rust.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 9a258d6e..3a6c3881 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -124,6 +124,12 @@ jobs: if: matrix.os.name == 'macOS' run: echo "LIBRARY_PATH=$(brew --prefix)/lib:$LIBRARY_PATH" >> $GITHUB_ENV + - name: Install CMake on MacOS + if: matrix.os.name == 'macOS' + run: | + brew ls --versions cmake >/dev/null 2>&1 || brew install cmake + cmake --version + - name: Install MPIR on Windows if: matrix.os.name == 'Windows' run: | From 8fc91e6dd56a408ecf890ce395895da7e60d37fa Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Mon, 9 Feb 2026 13:30:13 -0800 Subject: [PATCH 16/78] more install cmake --- .github/workflows/rust.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 3a6c3881..25b3b99b 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -128,6 +128,17 @@ jobs: if: matrix.os.name == 'macOS' run: | brew ls --versions cmake >/dev/null 2>&1 || brew install cmake + CMAKE_BIN="$(brew --prefix cmake)/bin" + if [ -d "$CMAKE_BIN" ]; then + echo "$CMAKE_BIN" >> "$GITHUB_PATH" + export PATH="$CMAKE_BIN:$PATH" + fi + if ! command -v cmake >/dev/null 2>&1; then + BREW_BIN="$(brew --prefix)/bin" + echo "$BREW_BIN" >> "$GITHUB_PATH" + export PATH="$BREW_BIN:$PATH" + fi + command -v cmake cmake --version - name: Install MPIR on Windows From 313c353105af93824999ff7c36d49810e87fbf1d Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Mon, 9 Feb 2026 13:40:56 -0800 Subject: [PATCH 17/78] fix ASAN, remove TSAN for windows runners --- .github/workflows/test.yaml | 42 ++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 9151bf51..2e6a7319 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -21,6 +21,11 @@ jobs: matrix: os: [macos-13-intel, macos-13-arm64, ubuntu-latest, windows-latest] config: [optimized=1, TSAN=1, ASAN=1] + exclude: + # clang-cl TSAN is unsupported for x86_64-pc-windows-msvc, so + # Windows TSAN fails during CMake compiler checks. + - os: windows-latest + config: TSAN=1 steps: - name: Checkout code @@ -100,18 +105,35 @@ jobs: $cmakeModuleLinkerFlags = "" if ("${{ matrix.config }}" -eq "ASAN=1") { $cmakeBuildType = "RelWithDebInfo" - $cmakeCFlags = "-fsanitize=address" - $cmakeCxxFlags = "-fsanitize=address" - $cmakeExeLinkerFlags = "-fsanitize=address" - $cmakeSharedLinkerFlags = "-fsanitize=address" - $cmakeModuleLinkerFlags = "-fsanitize=address" + # clang-cl on Windows expects /fsanitize=address, and lld-link does + # not understand -fsanitize=address linker flags. + $cmakeCFlags = "/fsanitize=address" + $cmakeCxxFlags = "/fsanitize=address" + $clangResourceDir = (& clang-cl --print-resource-dir).Trim() + $asanLibDir = Join-Path $clangResourceDir "lib\windows" + if (-not (Test-Path $asanLibDir)) { + throw "ASAN runtime library directory not found: $asanLibDir" + } + if ($env:LIB) { + $env:LIB = "$asanLibDir;$env:LIB" + } else { + $env:LIB = "$asanLibDir" + } } elseif ("${{ matrix.config }}" -eq "TSAN=1") { $cmakeBuildType = "RelWithDebInfo" - $cmakeCFlags = "-fsanitize=thread" - $cmakeCxxFlags = "-fsanitize=thread" - $cmakeExeLinkerFlags = "-fsanitize=thread" - $cmakeSharedLinkerFlags = "-fsanitize=thread" - $cmakeModuleLinkerFlags = "-fsanitize=thread" + # Keep sanitizer flag on compile side for clang-cl. + $cmakeCFlags = "/fsanitize=thread" + $cmakeCxxFlags = "/fsanitize=thread" + $clangResourceDir = (& clang-cl --print-resource-dir).Trim() + $tsanLibDir = Join-Path $clangResourceDir "lib\windows" + if (-not (Test-Path $tsanLibDir)) { + throw "TSAN runtime library directory not found: $tsanLibDir" + } + if ($env:LIB) { + $env:LIB = "$tsanLibDir;$env:LIB" + } else { + $env:LIB = "$tsanLibDir" + } } # Force compiler probes (try_compile) to use release CRT when # sanitizers are enabled; clang-cl rejects /MDd + -fsanitize=address. From a9c401fe9bb5b9cd3ee7dacfa3ead8b48e084e5e Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Mon, 9 Feb 2026 13:48:19 -0800 Subject: [PATCH 18/78] initiate windows dev env on ASAN runner --- .github/workflows/test.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 2e6a7319..17e0492e 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -93,6 +93,12 @@ jobs: fetch-depth: 1 path: mpir_gc_x64 + - name: Set up MSVC environment (Windows SDK + CRT libs) + if: startsWith(matrix.os, 'windows') + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + - name: Build vdf-client on Windows if: startsWith(matrix.os, 'windows') shell: pwsh From e4d821ef40667593ca5862b395635bbecde34734 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Mon, 9 Feb 2026 13:59:43 -0800 Subject: [PATCH 19/78] more ASAN windows issues - harden brew handling in cibuildwheel --- .github/workflows/test.yaml | 15 ++++++++++++++- pyproject.toml | 27 +++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 17e0492e..151d3198 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -112,7 +112,8 @@ jobs: if ("${{ matrix.config }}" -eq "ASAN=1") { $cmakeBuildType = "RelWithDebInfo" # clang-cl on Windows expects /fsanitize=address, and lld-link does - # not understand -fsanitize=address linker flags. + # not understand -fsanitize=address linker flags. CMake links probes + # with lld-link directly, so add ASAN runtimes explicitly. $cmakeCFlags = "/fsanitize=address" $cmakeCxxFlags = "/fsanitize=address" $clangResourceDir = (& clang-cl --print-resource-dir).Trim() @@ -120,6 +121,18 @@ jobs: if (-not (Test-Path $asanLibDir)) { throw "ASAN runtime library directory not found: $asanLibDir" } + $asanRuntimeLib = Join-Path $asanLibDir "clang_rt.asan_dynamic-x86_64.lib" + $asanThunkLib = Join-Path $asanLibDir "clang_rt.asan_dynamic_runtime_thunk-x86_64.lib" + if (-not (Test-Path $asanRuntimeLib)) { + throw "ASAN runtime library not found: $asanRuntimeLib" + } + if (-not (Test-Path $asanThunkLib)) { + throw "ASAN runtime thunk library not found: $asanThunkLib" + } + $asanLinkLibs = "clang_rt.asan_dynamic_runtime_thunk-x86_64.lib clang_rt.asan_dynamic-x86_64.lib" + $cmakeExeLinkerFlags = $asanLinkLibs + $cmakeSharedLinkerFlags = $asanLinkLibs + $cmakeModuleLinkerFlags = $asanLinkLibs if ($env:LIB) { $env:LIB = "$asanLibDir;$env:LIB" } else { diff --git a/pyproject.toml b/pyproject.toml index 55a04341..8142098a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,8 +33,31 @@ before-build = "python -m pip install --upgrade pip" [tool.cibuildwheel.macos] build-verbosity = 0 before-all = """ -brew --prefix --installed gmp >/dev/null 2>&1 || brew install gmp -brew install boost cmake +set -euo pipefail +export HOMEBREW_NO_AUTO_UPDATE=1 + +brew_install_if_missing() { + pkg="$1" + if brew list --versions "$pkg" >/dev/null 2>&1; then + echo "$pkg already installed" + return 0 + fi + + for attempt in 1 2 3; do + if brew install "$pkg"; then + return 0 + fi + echo "brew install $pkg failed (attempt $attempt), retrying..." + sleep $((attempt * 5)) + done + + echo "Failed to install $pkg after retries" + return 1 +} + +brew_install_if_missing gmp +brew_install_if_missing boost +brew_install_if_missing cmake """ before-build = "python -m pip install --upgrade pip" environment = {MACOSX_DEPLOYMENT_TARGET="13", SYSTEM_VERSION_COMPAT=0, BUILD_VDF_CLIENT="N"} From 7df51ce3292e3a789097f677ec10db4b4ca2e849 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Mon, 9 Feb 2026 14:26:20 -0800 Subject: [PATCH 20/78] giving up on ASAN --- .github/workflows/test.yaml | 61 ++----------------------------------- 1 file changed, 2 insertions(+), 59 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 151d3198..4c395553 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -22,8 +22,8 @@ jobs: os: [macos-13-intel, macos-13-arm64, ubuntu-latest, windows-latest] config: [optimized=1, TSAN=1, ASAN=1] exclude: - # clang-cl TSAN is unsupported for x86_64-pc-windows-msvc, so - # Windows TSAN fails during CMake compiler checks. + - os: windows-latest + config: ASAN=1 - os: windows-latest config: TSAN=1 @@ -104,58 +104,6 @@ jobs: shell: pwsh run: | $cmakeBuildType = "Release" - $cmakeCFlags = "" - $cmakeCxxFlags = "" - $cmakeExeLinkerFlags = "" - $cmakeSharedLinkerFlags = "" - $cmakeModuleLinkerFlags = "" - if ("${{ matrix.config }}" -eq "ASAN=1") { - $cmakeBuildType = "RelWithDebInfo" - # clang-cl on Windows expects /fsanitize=address, and lld-link does - # not understand -fsanitize=address linker flags. CMake links probes - # with lld-link directly, so add ASAN runtimes explicitly. - $cmakeCFlags = "/fsanitize=address" - $cmakeCxxFlags = "/fsanitize=address" - $clangResourceDir = (& clang-cl --print-resource-dir).Trim() - $asanLibDir = Join-Path $clangResourceDir "lib\windows" - if (-not (Test-Path $asanLibDir)) { - throw "ASAN runtime library directory not found: $asanLibDir" - } - $asanRuntimeLib = Join-Path $asanLibDir "clang_rt.asan_dynamic-x86_64.lib" - $asanThunkLib = Join-Path $asanLibDir "clang_rt.asan_dynamic_runtime_thunk-x86_64.lib" - if (-not (Test-Path $asanRuntimeLib)) { - throw "ASAN runtime library not found: $asanRuntimeLib" - } - if (-not (Test-Path $asanThunkLib)) { - throw "ASAN runtime thunk library not found: $asanThunkLib" - } - $asanLinkLibs = "clang_rt.asan_dynamic_runtime_thunk-x86_64.lib clang_rt.asan_dynamic-x86_64.lib" - $cmakeExeLinkerFlags = $asanLinkLibs - $cmakeSharedLinkerFlags = $asanLinkLibs - $cmakeModuleLinkerFlags = $asanLinkLibs - if ($env:LIB) { - $env:LIB = "$asanLibDir;$env:LIB" - } else { - $env:LIB = "$asanLibDir" - } - } elseif ("${{ matrix.config }}" -eq "TSAN=1") { - $cmakeBuildType = "RelWithDebInfo" - # Keep sanitizer flag on compile side for clang-cl. - $cmakeCFlags = "/fsanitize=thread" - $cmakeCxxFlags = "/fsanitize=thread" - $clangResourceDir = (& clang-cl --print-resource-dir).Trim() - $tsanLibDir = Join-Path $clangResourceDir "lib\windows" - if (-not (Test-Path $tsanLibDir)) { - throw "TSAN runtime library directory not found: $tsanLibDir" - } - if ($env:LIB) { - $env:LIB = "$tsanLibDir;$env:LIB" - } else { - $env:LIB = "$tsanLibDir" - } - } - # Force compiler probes (try_compile) to use release CRT when - # sanitizers are enabled; clang-cl rejects /MDd + -fsanitize=address. $cmakeArgs = @( "-S", "src", "-B", "build", @@ -166,11 +114,6 @@ jobs: "-DCMAKE_C_COMPILER=clang-cl", "-DCMAKE_CXX_COMPILER=clang-cl", "-DCMAKE_ASM_COMPILER=clang-cl", - "-DCMAKE_C_FLAGS=$cmakeCFlags", - "-DCMAKE_CXX_FLAGS=$cmakeCxxFlags", - "-DCMAKE_EXE_LINKER_FLAGS=$cmakeExeLinkerFlags", - "-DCMAKE_SHARED_LINKER_FLAGS=$cmakeSharedLinkerFlags", - "-DCMAKE_MODULE_LINKER_FLAGS=$cmakeModuleLinkerFlags", "-DBOOST_INCLUDE_DIR=$env:BOOST_INCLUDE_DIR", "-DBUILD_PYTHON=OFF", "-DBUILD_CHIAVDFC=OFF", From f0e2ce6dede83e2dea6d24ad16bdf120c6b18120 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Mon, 9 Feb 2026 15:14:13 -0800 Subject: [PATCH 21/78] Add required linker flag for Windows asm - fix unchecked vector access --- src/CMakeLists.txt | 6 ++++++ src/vdf_base_integer.cpp | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dd021f01..658b1452 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -283,6 +283,8 @@ if(BUILD_VDF_TESTS) endif() vdf_add_boost_includes(1weso_test) target_link_libraries(1weso_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + vdf_add_windows_asm_linker_flags(1weso_test) + vdf_add_windows_clang_opts(1weso_test) add_executable(2weso_test ${CMAKE_CURRENT_SOURCE_DIR}/2weso_test.cpp @@ -294,6 +296,8 @@ if(BUILD_VDF_TESTS) endif() vdf_add_boost_includes(2weso_test) target_link_libraries(2weso_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + vdf_add_windows_asm_linker_flags(2weso_test) + vdf_add_windows_clang_opts(2weso_test) add_executable(prover_test ${CMAKE_CURRENT_SOURCE_DIR}/prover_test.cpp @@ -305,6 +309,8 @@ if(BUILD_VDF_TESTS) endif() vdf_add_boost_includes(prover_test) target_link_libraries(prover_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + vdf_add_windows_asm_linker_flags(prover_test) + vdf_add_windows_clang_opts(prover_test) endif() if(BUILD_HW_TOOLS) diff --git a/src/vdf_base_integer.cpp b/src/vdf_base_integer.cpp index bd5e21ec..2e4b02b1 100644 --- a/src/vdf_base_integer.cpp +++ b/src/vdf_base_integer.cpp @@ -327,7 +327,8 @@ bool form::operator<(const form& f) const { } int form::hash() const { - uint64 res = c.to_vector()[0]; + const auto c_vector = c.to_vector(); + uint64 res = c_vector.empty() ? 0 : c_vector[0]; return int((res >> 4) & ((1ull << 31) - 1)); } From dc36ee810c0f5bf45be1263e3af9df14b980addd Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Mon, 9 Feb 2026 15:49:18 -0800 Subject: [PATCH 22/78] potentially fix bug in the 2weso test --- src/2weso_test.cpp | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/2weso_test.cpp b/src/2weso_test.cpp index be9c12ab..1e2a0bd2 100644 --- a/src/2weso_test.cpp +++ b/src/2weso_test.cpp @@ -56,21 +56,31 @@ int main(int argc, char const* argv[]) try TwoWesolowskiCallback weso(D, f); FastStorage* fast_storage = NULL; std::thread vdf_worker(repeated_square, 0, f, D, L, &weso, fast_storage, std::ref(stopped)); - // Test 1 - 1 million iters. - uint64_t iteration = 1 * iter_multiplier; - Proof proof = ProveTwoWeso(D, f, iteration, 0, &weso, 0, stopped); - CheckProof(D, proof, iteration); - // Test 2 - 15 million iters. - iteration = 15 * iter_multiplier; - proof = ProveTwoWeso(D, f, iteration, 0, &weso, 0, stopped); - CheckProof(D, proof, iteration); - // Test 3 - 100 million iters. - iteration = 100 * iter_multiplier; - proof = ProveTwoWeso(D, f, iteration, 0, &weso, 0, stopped); - CheckProof(D, proof, iteration); - // Test stopping gracefully. - stopped = true; - vdf_worker.join(); + auto stop_worker = [&]() { + stopped = true; + if (vdf_worker.joinable()) { + vdf_worker.join(); + } + }; + try { + // Test 1 - 1 million iters. + uint64_t iteration = 1 * iter_multiplier; + Proof proof = ProveTwoWeso(D, f, iteration, 0, &weso, 0, stopped); + CheckProof(D, proof, iteration); + // Test 2 - 15 million iters. + iteration = 15 * iter_multiplier; + proof = ProveTwoWeso(D, f, iteration, 0, &weso, 0, stopped); + CheckProof(D, proof, iteration); + // Test 3 - 100 million iters. + iteration = 100 * iter_multiplier; + proof = ProveTwoWeso(D, f, iteration, 0, &weso, 0, stopped); + CheckProof(D, proof, iteration); + // Test stopping gracefully. + stop_worker(); + } catch (...) { + stop_worker(); + throw; + } return 0; } catch (std::exception const& e) { From a72c490362fdcaca5e2f516e956c7a740ab89a47 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Tue, 10 Feb 2026 19:20:10 -0800 Subject: [PATCH 23/78] consolidate 2weso fail-hunting phases 40-43 Collapse the contiguous phase-40 through phase-43 debug commits into one checkpoint while preserving the net tree state before phase 44. Co-authored-by: Cursor --- .github/workflows/test.yaml | 21 + src/2weso_test.cpp | 244 ++++++- src/callback.h | 750 +++++++++++++++++++- src/prover_base.hpp | 1286 +++++++++++++++++++++++++++++++++++ src/provers.h | 518 +++++++++++++- src/vdf.h | 236 ++++++- 6 files changed, 3036 insertions(+), 19 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 4c395553..00817d26 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -167,6 +167,10 @@ jobs: if: matrix.config == 'optimized=1' && startsWith(matrix.os, 'windows') shell: pwsh run: | + Write-Host "CI commit (HEAD): $env:GITHUB_SHA" + git rev-parse --short HEAD + Write-Host "Instrumentation marker source line:" + Select-String -Path "$env:GITHUB_WORKSPACE\src\2weso_test.cpp" -Pattern 'instrumentation_version' | ForEach-Object { $_.Line } cd build $dllPaths = @() if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } @@ -177,14 +181,31 @@ jobs: & ".\$name.exe" @args if ($LASTEXITCODE -ne 0) { Write-Host "$name exit code: $LASTEXITCODE" + if ($name -eq "2weso_test" -and (Test-Path $env:CHIAVDF_AGENT_DEBUG_LOG)) { + Write-Host "=== 2weso debug log start ===" + Get-Content $env:CHIAVDF_AGENT_DEBUG_LOG + Write-Host "=== 2weso debug log end ===" + } exit $LASTEXITCODE } } + $env:CHIAVDF_AGENT_DEBUG_LOG = "$env:GITHUB_WORKSPACE\2weso-debug.ndjson" + if (Test-Path $env:CHIAVDF_AGENT_DEBUG_LOG) { Remove-Item $env:CHIAVDF_AGENT_DEBUG_LOG -Force } Invoke-TestExe "1weso_test" + Write-Host "Running 2weso_test quick precheck (100)" + Invoke-TestExe "2weso_test" @("100") Invoke-TestExe "2weso_test" $env:CHIAVDF_PROVER_TEST_FAST = "1" Invoke-TestExe "prover_test" + - name: Upload 2weso debug artifact (Windows) + if: matrix.config == 'optimized=1' && startsWith(matrix.os, 'windows') && always() + uses: actions/upload-artifact@v4 + with: + name: 2weso-debug-windows + path: ${{ github.workspace }}/2weso-debug.ndjson + if-no-files-found: ignore + - name: Benchmark vdf_bench square (Ubuntu/Mac) if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') run: | diff --git a/src/2weso_test.cpp b/src/2weso_test.cpp index 1e2a0bd2..4f0fd8aa 100644 --- a/src/2weso_test.cpp +++ b/src/2weso_test.cpp @@ -3,6 +3,12 @@ #include "verifier.h" #include +#include +#include +#include +#include +#include +#include int segments = 7; int thread_count = 3; @@ -10,14 +16,99 @@ int thread_count = 3; int gcd_base_bits=50; int gcd_128_max_iter=3; +namespace { +std::atomic g_agent_log_seq{0}; + +const char* AgentDebugLogPath() { + const char* env_path = std::getenv("CHIAVDF_AGENT_DEBUG_LOG"); + if (env_path != nullptr && env_path[0] != '\0') { + return env_path; + } + return "/Users/hoffmang/src/chiavdf/.cursor/debug.log"; +} + +bool AgentDebugShouldMirror(const char* hypothesis_id) { + const char* mirror_all = std::getenv("CHIAVDF_AGENT_DEBUG_MIRROR_ALL"); + if (mirror_all != nullptr && mirror_all[0] == '1') { + return true; + } + return std::strcmp(hypothesis_id, "H14") == 0 || + std::strcmp(hypothesis_id, "H16") == 0 || + std::strcmp(hypothesis_id, "H18") == 0 || + std::strcmp(hypothesis_id, "H19") == 0 || + std::strcmp(hypothesis_id, "H22") == 0 || + std::strcmp(hypothesis_id, "H28") == 0 || + std::strcmp(hypothesis_id, "H29") == 0 || + std::strcmp(hypothesis_id, "H36") == 0 || + std::strcmp(hypothesis_id, "H37") == 0; +} + +void AgentDebugLog(const char* run_id, const char* hypothesis_id, const char* location, const char* message, const std::string& data_json) { + std::ofstream out(AgentDebugLogPath(), std::ios::app); + if (!out.is_open()) { + return; + } + const auto ts = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); + const uint64_t seq = ++g_agent_log_seq; + out << "{\"id\":\"log_" << ts << "_" << seq + << "\",\"timestamp\":" << ts + << ",\"runId\":\"" << run_id + << "\",\"hypothesisId\":\"" << hypothesis_id + << "\",\"location\":\"" << location + << "\",\"message\":\"" << message + << "\",\"data\":" << data_json + << "}\n"; + if (AgentDebugShouldMirror(hypothesis_id)) { + std::cerr << "AGENTLOG " + << "{\"id\":\"log_" << ts << "_" << seq + << "\",\"timestamp\":" << ts + << ",\"runId\":\"" << run_id + << "\",\"hypothesisId\":\"" << hypothesis_id + << "\",\"location\":\"" << location + << "\",\"message\":\"" << message + << "\",\"data\":" << data_json + << "}\n"; + } +} +} + void CheckProof(integer& D, Proof& proof, uint64_t iteration) { form x = form::generator(D); std::vector bytes; bytes.insert(bytes.end(), proof.y.begin(), proof.y.end()); bytes.insert(bytes.end(), proof.proof.begin(), proof.proof.end()); + // #region agent log + AgentDebugLog( + "pre-fix", + "H3", + "2weso_test.cpp:CheckProof:before_verify", + "CheckProof start", + std::string("{\"iteration\":") + std::to_string(iteration) + + ",\"y_size\":" + std::to_string(proof.y.size()) + + ",\"proof_size\":" + std::to_string(proof.proof.size()) + + ",\"witness_type\":" + std::to_string(proof.witness_type) + "}"); + // #endregion if (CheckProofOfTimeNWesolowski(D, DEFAULT_ELEMENT, bytes.data(), bytes.size(), iteration, 1024, proof.witness_type)) { + // #region agent log + AgentDebugLog( + "pre-fix", + "H3", + "2weso_test.cpp:CheckProof:verify_true", + "CheckProof returned true", + std::string("{\"iteration\":") + std::to_string(iteration) + "}"); + // #endregion std::cout << "Correct proof\n"; } else { + // #region agent log + AgentDebugLog( + "pre-fix", + "H3", + "2weso_test.cpp:CheckProof:verify_false", + "CheckProof returned false", + std::string("{\"iteration\":") + std::to_string(iteration) + "}"); + // #endregion std::cout << "Incorrect proof\n"; throw std::runtime_error("incorrect proof"); } @@ -30,51 +121,190 @@ int main(int argc, char const* argv[]) try // specifically with instrumented binaries that aren't as fast std::uint64_t const iter_multiplier = (argc > 1) ? std::stoull(argv[1]) : 1000000; + // #region agent log + AgentDebugLog( + "post-fix", + "H37", + "2weso_test.cpp:main:instrumentation_version_marker", + "Instrumentation marker for artifact/version validation", + "{\"instrumentation_version\":\"H54\",\"source\":\"2weso_test\"}"); + // #endregion assert(is_vdf_test); //assertions should be disabled in VDF_MODE==0 init_gmp(); debug_mode = true; - if(hasAVX2()) + const bool has_avx2 = hasAVX2(); + if(has_avx2) { gcd_base_bits=63; gcd_128_max_iter=2; } + // #region agent log + AgentDebugLog( + "pre-fix", + "H5", + "2weso_test.cpp:main:post_cpu_init", + "CPU feature and gcd parameters set", + std::string("{\"iter_multiplier\":") + std::to_string(iter_multiplier) + + ",\"has_avx2\":" + (has_avx2 ? "true" : "false") + + ",\"gcd_base_bits\":" + std::to_string(gcd_base_bits) + + ",\"gcd_128_max_iter\":" + std::to_string(gcd_128_max_iter) + "}"); + // #endregion std::vector challenge_hash({0, 0, 1, 2, 3, 3, 4, 4}); + // #region agent log + AgentDebugLog( + "pre-fix", + "H6", + "2weso_test.cpp:main:before_create_discriminant", + "About to call CreateDiscriminant", + "{\"bits\":1024,\"challenge_hash_size\":8}"); + // #endregion integer D = CreateDiscriminant(challenge_hash, 1024); + // #region agent log + AgentDebugLog( + "pre-fix", + "H6", + "2weso_test.cpp:main:after_create_discriminant", + "CreateDiscriminant returned", + std::string("{\"discriminant_sign\":") + (D < 0 ? "-1" : "1") + "}"); + // #endregion if (getenv( "warn_on_corruption_in_production" )!=nullptr) { warn_on_corruption_in_production=true; } + // #region agent log + AgentDebugLog( + "pre-fix", + "H7", + "2weso_test.cpp:main:after_warn_env", + "warn_on_corruption flag evaluated", + std::string("{\"warn_on_corruption_in_production\":") + + (warn_on_corruption_in_production ? "true" : "false") + "}"); + // #endregion set_rounding_mode(); + // #region agent log + AgentDebugLog( + "pre-fix", + "H8", + "2weso_test.cpp:main:after_set_rounding_mode", + "set_rounding_mode completed", + "{}"); + // #endregion + // #region agent log + AgentDebugLog( + "pre-fix", + "H9", + "2weso_test.cpp:main:before_root_generator", + "About to compute L and generator", + "{}"); + // #endregion integer L=root(-D, 4); form f=form::generator(D); + // #region agent log + AgentDebugLog( + "pre-fix", + "H9", + "2weso_test.cpp:main:after_root_generator", + "Computed L and generator", + "{}"); + // #endregion std::atomic stopped = false; fast_algorithm = false; two_weso = true; + // #region agent log + AgentDebugLog( + "pre-fix", + "H10", + "2weso_test.cpp:main:before_callback_ctor", + "About to construct TwoWesolowskiCallback", + "{}"); + // #endregion + const uint64_t max_test_iteration = 100 * iter_multiplier; TwoWesolowskiCallback weso(D, f); + // #region agent log + AgentDebugLog( + "pre-fix", + "H10", + "2weso_test.cpp:main:after_callback_ctor", + "Constructed TwoWesolowskiCallback", + "{}"); + // #endregion FastStorage* fast_storage = NULL; + // #region agent log + AgentDebugLog( + "pre-fix", + "H1", + "2weso_test.cpp:main:before_worker_start", + "Starting repeated_square worker thread", + std::string("{\"fast_algorithm\":") + (fast_algorithm ? "true" : "false") + + ",\"two_weso\":" + (two_weso ? "true" : "false") + "}"); + // #endregion std::thread vdf_worker(repeated_square, 0, f, D, L, &weso, fast_storage, std::ref(stopped)); + // #region agent log + AgentDebugLog( + "pre-fix", + "H1", + "2weso_test.cpp:main:after_worker_start", + "Worker thread started", + std::string("{\"worker_joinable\":") + (vdf_worker.joinable() ? "true" : "false") + "}"); + // #endregion auto stop_worker = [&]() { + // #region agent log + AgentDebugLog( + "pre-fix", + "H4", + "2weso_test.cpp:main:stop_worker_enter", + "stop_worker invoked", + std::string("{\"worker_joinable_before\":") + (vdf_worker.joinable() ? "true" : "false") + "}"); + // #endregion stopped = true; if (vdf_worker.joinable()) { vdf_worker.join(); } + // #region agent log + AgentDebugLog( + "pre-fix", + "H4", + "2weso_test.cpp:main:stop_worker_exit", + "stop_worker completed", + std::string("{\"worker_joinable_after\":") + (vdf_worker.joinable() ? "true" : "false") + "}"); + // #endregion }; try { + auto run_test = [&](uint64_t iteration) { + // #region agent log + AgentDebugLog( + "pre-fix", + "H2", + "2weso_test.cpp:main:before_prove", + "Calling ProveTwoWeso", + std::string("{\"iteration\":") + std::to_string(iteration) + "}"); + // #endregion + Proof proof = ProveTwoWeso(D, f, iteration, 0, &weso, 0, stopped); + // #region agent log + AgentDebugLog( + "pre-fix", + "H2", + "2weso_test.cpp:main:after_prove", + "ProveTwoWeso returned", + std::string("{\"iteration\":") + std::to_string(iteration) + + ",\"y_size\":" + std::to_string(proof.y.size()) + + ",\"proof_size\":" + std::to_string(proof.proof.size()) + + ",\"witness_type\":" + std::to_string(proof.witness_type) + "}"); + // #endregion + CheckProof(D, proof, iteration); + }; // Test 1 - 1 million iters. uint64_t iteration = 1 * iter_multiplier; - Proof proof = ProveTwoWeso(D, f, iteration, 0, &weso, 0, stopped); - CheckProof(D, proof, iteration); + run_test(iteration); // Test 2 - 15 million iters. iteration = 15 * iter_multiplier; - proof = ProveTwoWeso(D, f, iteration, 0, &weso, 0, stopped); - CheckProof(D, proof, iteration); + run_test(iteration); // Test 3 - 100 million iters. iteration = 100 * iter_multiplier; - proof = ProveTwoWeso(D, f, iteration, 0, &weso, 0, stopped); - CheckProof(D, proof, iteration); + run_test(iteration); // Test stopping gracefully. stop_worker(); } catch (...) { diff --git a/src/callback.h b/src/callback.h index 9da2f9ce..d7b33a42 100644 --- a/src/callback.h +++ b/src/callback.h @@ -3,6 +3,15 @@ #include "util.h" #include "nudupl_listener.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include // Applies to n-weso. const int kWindowSize = 20; @@ -11,13 +20,99 @@ const int kWindowSize = 20; const int kMaxItersAllowed = 8e8; const int kSwitchIters = 91000000; +inline const char* CallbackAgentDebugLogPath() { + const char* env_path = std::getenv("CHIAVDF_AGENT_DEBUG_LOG"); + if (env_path != nullptr && env_path[0] != '\0') { + return env_path; + } + return "/Users/hoffmang/src/chiavdf/.cursor/debug.log"; +} + +inline bool CallbackAgentDebugShouldMirror(const char* hypothesis_id) { + const char* mirror_all = std::getenv("CHIAVDF_AGENT_DEBUG_MIRROR_ALL"); + if (mirror_all != nullptr && mirror_all[0] == '1') { + return true; + } + return std::strcmp(hypothesis_id, "H14") == 0 || + std::strcmp(hypothesis_id, "H16") == 0 || + std::strcmp(hypothesis_id, "H18") == 0 || + std::strcmp(hypothesis_id, "H19") == 0 || + std::strcmp(hypothesis_id, "H22") == 0 || + std::strcmp(hypothesis_id, "H28") == 0 || + std::strcmp(hypothesis_id, "H29") == 0 || + std::strcmp(hypothesis_id, "H32") == 0 || + std::strcmp(hypothesis_id, "H33") == 0 || + std::strcmp(hypothesis_id, "H34") == 0 || + std::strcmp(hypothesis_id, "H35") == 0 || + std::strcmp(hypothesis_id, "H36") == 0 || + std::strcmp(hypothesis_id, "H38") == 0 || + std::strcmp(hypothesis_id, "H39") == 0 || + std::strcmp(hypothesis_id, "H40") == 0 || + std::strcmp(hypothesis_id, "H41") == 0 || + std::strcmp(hypothesis_id, "H42") == 0 || + std::strcmp(hypothesis_id, "H43") == 0 || + std::strcmp(hypothesis_id, "H44") == 0 || + std::strcmp(hypothesis_id, "H45") == 0 || + std::strcmp(hypothesis_id, "H46") == 0 || + std::strcmp(hypothesis_id, "H47") == 0 || + std::strcmp(hypothesis_id, "H48") == 0 || + std::strcmp(hypothesis_id, "H49") == 0 || + std::strcmp(hypothesis_id, "H50") == 0 || + std::strcmp(hypothesis_id, "H51") == 0 || + std::strcmp(hypothesis_id, "H53") == 0 || + std::strcmp(hypothesis_id, "H54") == 0; +} + +inline void CallbackAgentDebugLog(const char* run_id, const char* hypothesis_id, const char* location, const char* message, const std::string& data_json) { + static std::atomic seq{0}; + std::ofstream out(CallbackAgentDebugLogPath(), std::ios::app); + if (!out.is_open()) { + return; + } + const auto ts = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); + const uint64_t id = ++seq; + out << "{\"id\":\"log_" << ts << "_" << id + << "\",\"timestamp\":" << ts + << ",\"runId\":\"" << run_id + << "\",\"hypothesisId\":\"" << hypothesis_id + << "\",\"location\":\"" << location + << "\",\"message\":\"" << message + << "\",\"data\":" << data_json + << "}\n"; + if (CallbackAgentDebugShouldMirror(hypothesis_id)) { + std::cerr << "AGENTLOG " + << "{\"id\":\"log_" << ts << "_" << id + << "\",\"timestamp\":" << ts + << ",\"runId\":\"" << run_id + << "\",\"hypothesisId\":\"" << hypothesis_id + << "\",\"location\":\"" << location + << "\",\"message\":\"" << message + << "\",\"data\":" << data_json + << "}\n"; + } +} + class WesolowskiCallback :public INUDUPLListener { public: WesolowskiCallback(integer& D) { + // #region agent log + CallbackAgentDebugLog("pre-fix", "H11", "callback.h:WesolowskiCallback:ctor_enter", "Entering WesolowskiCallback constructor", "{}"); + // #endregion vdfo = new vdf_original(); + // #region agent log + CallbackAgentDebugLog("pre-fix", "H11", "callback.h:WesolowskiCallback:after_vdfo_new", "Allocated vdf_original", "{}"); + // #endregion reducer = new PulmarkReducer(); + // #region agent log + CallbackAgentDebugLog("pre-fix", "H11", "callback.h:WesolowskiCallback:after_reducer_new", "Allocated PulmarkReducer", "{}"); + // #endregion this->D = D; this->L = root(-D, 4); + // #region agent log + CallbackAgentDebugLog("pre-fix", "H11", "callback.h:WesolowskiCallback:ctor_exit", "Leaving WesolowskiCallback constructor", "{}"); + // #endregion } virtual ~WesolowskiCallback() { @@ -70,6 +165,7 @@ class WesolowskiCallback :public INUDUPLListener { virtual void OnIteration(int type, void *data, uint64_t iteration) = 0; std::unique_ptr forms; + size_t forms_capacity = 0; std::atomic iterations{0}; integer D; integer L; @@ -90,6 +186,7 @@ class OneWesolowskiCallback: public WesolowskiCallback { } kl = k * l; uint64_t space_needed = wanted_iter / (k * l) + 100; + forms_capacity = static_cast(space_needed); forms.reset(new form[space_needed]); forms[0] = f; } @@ -116,12 +213,102 @@ class OneWesolowskiCallback: public WesolowskiCallback { class TwoWesolowskiCallback: public WesolowskiCallback { public: - TwoWesolowskiCallback(integer& D, form f) : WesolowskiCallback(D) { - int space_needed = kSwitchIters / 10 + (kMaxItersAllowed - kSwitchIters) / 100; + TwoWesolowskiCallback(integer& D, const form& f) : WesolowskiCallback(D) { + // #region agent log + CallbackAgentDebugLog("pre-fix", "H12", "callback.h:TwoWesolowskiCallback:ctor_enter", "Entering TwoWesolowskiCallback constructor", "{}"); + // #endregion + const uint64_t early_points = static_cast(kSwitchIters) / 10; + const uint64_t late_points = + (static_cast(kMaxItersAllowed) - static_cast(kSwitchIters)) / 100; + const size_t space_needed = static_cast(early_points + late_points); + forms_capacity = space_needed; + // #region agent log + CallbackAgentDebugLog( + "pre-fix", + "H12", + "callback.h:TwoWesolowskiCallback:before_forms_alloc", + "Allocating forms array", + std::string("{\"space_needed\":") + std::to_string(space_needed) + + ",\"max_iters_fixed\":" + std::to_string(kMaxItersAllowed) + "}"); + // #endregion forms.reset(new form[space_needed]); + // #region agent log + CallbackAgentDebugLog("pre-fix", "H12", "callback.h:TwoWesolowskiCallback:after_forms_alloc", "Allocated forms array", "{}"); + // #endregion + // #region agent log + CallbackAgentDebugLog("pre-fix", "H13", "callback.h:TwoWesolowskiCallback:before_seed_form_assign", "Assigning initial form to forms[0]", "{}"); + // #endregion + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H54", + "callback.h:TwoWesolowskiCallback:seed_h54_stage0_pre_source_reads", + "H54 before reading source num_bits", + "{}"); + // #endregion + const uint64_t source_a_bits = static_cast(f.a.num_bits()); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H54", + "callback.h:TwoWesolowskiCallback:seed_h54_stage1_after_a_bits", + "H54 after reading source a bits", + std::string("{\"source_a_bits\":") + std::to_string(source_a_bits) + "}"); + // #endregion + const uint64_t source_b_bits = static_cast(f.b.num_bits()); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H54", + "callback.h:TwoWesolowskiCallback:seed_h54_stage2_after_b_bits", + "H54 after reading source b bits", + std::string("{\"source_b_bits\":") + std::to_string(source_b_bits) + "}"); + // #endregion + const uint64_t source_c_bits = static_cast(f.c.num_bits()); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H54", + "callback.h:TwoWesolowskiCallback:seed_h54_stage3_after_c_bits", + "H54 after reading source c bits", + std::string("{\"source_c_bits\":") + std::to_string(source_c_bits) + "}"); + // #endregion + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H53", + "callback.h:TwoWesolowskiCallback:seed_stage0_source_state", + "H53 source form state before seed assignment", + std::string("{\"source_a_bits\":") + std::to_string(source_a_bits) + + ",\"source_b_bits\":" + std::to_string(source_b_bits) + + ",\"source_c_bits\":" + std::to_string(source_c_bits) + "}"); + // #endregion + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H53", + "callback.h:TwoWesolowskiCallback:seed_stage1_dest_slot", + "H53 destination slot prepared for seed assignment", + std::string("{\"forms_capacity\":") + std::to_string(forms_capacity) + "}"); + // #endregion forms[0] = f; + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H53", + "callback.h:TwoWesolowskiCallback:seed_stage2_after_assign", + "H53 seed assignment completed", + std::string("{\"stored_valid\":") + (forms[0].check_valid(D) ? "true" : "false") + + ",\"stored_a_bits\":" + std::to_string(forms[0].a.num_bits()) + "}"); + // #endregion + // #region agent log + CallbackAgentDebugLog("pre-fix", "H13", "callback.h:TwoWesolowskiCallback:after_seed_form_assign", "Assigned initial form to forms[0]", "{}"); + // #endregion kl = 10; switch_iters = -1; + // #region agent log + CallbackAgentDebugLog("pre-fix", "H12", "callback.h:TwoWesolowskiCallback:ctor_exit", "Leaving TwoWesolowskiCallback constructor", "{}"); + // #endregion } void IncreaseConstants(uint64_t num_iters) { @@ -138,8 +325,502 @@ class TwoWesolowskiCallback: public WesolowskiCallback { } } - form *GetForm(uint64_t power) { - return &(forms[GetPosition(power)]); + form GetFormCopy(uint64_t power) { + if (power >= 12500590 && power <= 12500610) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H47", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h47_stage0_pre_lock", + "H47 stage0 pre-lock", + std::string("{\"power\":") + std::to_string(power) + "}"); + // #endregion + } + if (power >= 12602260 && power <= 12602280) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H48", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h48_stage0_pre_lock", + "H48 stage0 pre-lock", + std::string("{\"power\":") + std::to_string(power) + "}"); + // #endregion + } + if (power >= 12500360 && power <= 12500390) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H49", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h49_stage0_pre_lock", + "H49 stage0 pre-lock", + std::string("{\"power\":") + std::to_string(power) + "}"); + // #endregion + } + if (power >= 12500920 && power <= 12500960) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H50", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h50_stage0_pre_lock", + "H50 stage0 pre-lock", + std::string("{\"power\":") + std::to_string(power) + "}"); + // #endregion + } + if (power >= 12500610 && power <= 12500630) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H51", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h51_stage0_pre_lock", + "H51 stage0 pre-lock", + std::string("{\"power\":") + std::to_string(power) + "}"); + // #endregion + } + std::lock_guard lk(forms_mutex); + if (power >= 12500590 && power <= 12500610) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H47", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h47_stage1_post_lock", + "H47 stage1 post-lock", + std::string("{\"power\":") + std::to_string(power) + "}"); + // #endregion + } + if (power >= 12602260 && power <= 12602280) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H48", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h48_stage1_post_lock", + "H48 stage1 post-lock", + std::string("{\"power\":") + std::to_string(power) + "}"); + // #endregion + } + if (power >= 12500360 && power <= 12500390) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H49", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h49_stage1_post_lock", + "H49 stage1 post-lock", + std::string("{\"power\":") + std::to_string(power) + "}"); + // #endregion + } + if (power >= 12500920 && power <= 12500960) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H50", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h50_stage1_post_lock", + "H50 stage1 post-lock", + std::string("{\"power\":") + std::to_string(power) + "}"); + // #endregion + } + if (power >= 12500610 && power <= 12500630) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H51", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h51_stage1_post_lock", + "H51 stage1 post-lock", + std::string("{\"power\":") + std::to_string(power) + "}"); + // #endregion + } + const int pos = GetPosition(power); + if (power >= 12500590 && power <= 12500610) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H47", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h47_stage2_after_getposition", + "H47 stage2 after GetPosition", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"forms_capacity\":" + std::to_string(forms_capacity) + "}"); + // #endregion + } + if (power >= 12602260 && power <= 12602280) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H48", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h48_stage2_after_getposition", + "H48 stage2 after GetPosition", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"forms_capacity\":" + std::to_string(forms_capacity) + "}"); + // #endregion + } + if (power >= 12500360 && power <= 12500390) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H49", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h49_stage2_after_getposition", + "H49 stage2 after GetPosition", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"forms_capacity\":" + std::to_string(forms_capacity) + "}"); + // #endregion + } + if (power >= 12500920 && power <= 12500960) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H50", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h50_stage2_after_getposition", + "H50 stage2 after GetPosition", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"forms_capacity\":" + std::to_string(forms_capacity) + "}"); + // #endregion + } + if (power >= 12500610 && power <= 12500630) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H51", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h51_stage2_after_getposition", + "H51 stage2 after GetPosition", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"forms_capacity\":" + std::to_string(forms_capacity) + "}"); + // #endregion + } + if (pos < 0 || static_cast(pos) >= forms_capacity) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H16", + "callback.h:TwoWesolowskiCallback:GetFormCopy_oob", + "GetFormCopy out of bounds", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"forms_capacity\":" + std::to_string(forms_capacity) + + ",\"switch_iters\":" + std::to_string(switch_iters) + + ",\"switch_index\":" + std::to_string(switch_index) + "}"); + // #endregion + throw std::runtime_error("TwoWesolowskiCallback::GetFormCopy out of bounds"); + } + if (power >= 12500590 && power <= 12500610) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H47", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h47_stage3_before_return_copy", + "H47 stage3 before return copy", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + "}"); + // #endregion + } + if (power >= 12500360 && power <= 12500390) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H49", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h49_stage3_before_source_deref", + "H49 stage3 before source dereference", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + "}"); + // #endregion + } + if (power >= 12500920 && power <= 12500960) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H50", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h50_stage3_before_source_deref", + "H50 stage3 before source dereference", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + "}"); + // #endregion + } + if (power >= 12500610 && power <= 12500630) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H51", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h51_stage3_before_source_deref", + "H51 stage3 before source dereference", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + "}"); + // #endregion + } + if (power >= 12650010 && power <= 12652000) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H32", + "callback.h:TwoWesolowskiCallback:GetFormCopy_micro_source_state", + "Micro window source form state before copy", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"source_valid\":" + (forms[static_cast(pos)].check_valid(D) ? "true" : "false") + + ",\"source_a_bits\":" + std::to_string(forms[static_cast(pos)].a.num_bits()) + "}"); + // #endregion + } + if (power >= 12644200 && power <= 12644450) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H34", + "callback.h:TwoWesolowskiCallback:GetFormCopy_focused_source_state", + "Focused window source form state before copy", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"source_valid\":" + (forms[static_cast(pos)].check_valid(D) ? "true" : "false") + + ",\"source_a_bits\":" + std::to_string(forms[static_cast(pos)].a.num_bits()) + "}"); + // #endregion + } + if (power >= 12647010 && power <= 12647600 && + !(power >= 12647080 && power <= 12647220)) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H35", + "callback.h:TwoWesolowskiCallback:GetFormCopy_post700_source_state", + "Post-264700 focused source form state before copy", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"source_valid\":" + (forms[static_cast(pos)].check_valid(D) ? "true" : "false") + + ",\"source_a_bits\":" + std::to_string(forms[static_cast(pos)].a.num_bits()) + "}"); + // #endregion + } + if (power >= 12647080 && power <= 12647220) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H39", + "callback.h:TwoWesolowskiCallback:GetFormCopy_stage0_before_source_deref", + "H39 stage0 before source dereference", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + "}"); + // #endregion + form& source = forms[static_cast(pos)]; + const bool source_valid = source.check_valid(D); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H39", + "callback.h:TwoWesolowskiCallback:GetFormCopy_stage1_after_check_valid", + "H39 stage1 after check_valid", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"source_valid\":" + (source_valid ? "true" : "false") + "}"); + // #endregion + const uint64_t source_a_bits = static_cast(source.a.num_bits()); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H39", + "callback.h:TwoWesolowskiCallback:GetFormCopy_stage2_after_num_bits", + "H39 stage2 after source num_bits", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"source_a_bits\":" + std::to_string(source_a_bits) + "}"); + // #endregion + } + if (power >= 12699800 && power <= 12700600) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H36", + "callback.h:TwoWesolowskiCallback:GetFormCopy_270k_source_state", + "270k window source form state before copy", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"source_valid\":" + (forms[static_cast(pos)].check_valid(D) ? "true" : "false") + + ",\"source_a_bits\":" + std::to_string(forms[static_cast(pos)].a.num_bits()) + "}"); + // #endregion + } + if (power >= 12643180 && power <= 12643240) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H38", + "callback.h:TwoWesolowskiCallback:GetFormCopy_crash_window_source_state", + "Crash-window source form state before copy", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"source_valid\":" + (forms[static_cast(pos)].check_valid(D) ? "true" : "false") + + ",\"source_a_bits\":" + std::to_string(forms[static_cast(pos)].a.num_bits()) + "}"); + // #endregion + } + if (power >= 12644100 && power <= 12644300) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H40", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h40_source_state", + "H40 window source form state before copy", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"source_valid\":" + (forms[static_cast(pos)].check_valid(D) ? "true" : "false") + + ",\"source_a_bits\":" + std::to_string(forms[static_cast(pos)].a.num_bits()) + "}"); + // #endregion + } + if (power >= 12635000 && power <= 12635200) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H41", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h41_stage0_before_source_deref", + "H41 stage0 before source dereference", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + "}"); + // #endregion + form& source = forms[static_cast(pos)]; + const bool source_valid = source.check_valid(D); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H41", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h41_stage1_after_check_valid", + "H41 stage1 after check_valid", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"source_valid\":" + (source_valid ? "true" : "false") + "}"); + // #endregion + const uint64_t source_a_bits = static_cast(source.a.num_bits()); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H41", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h41_stage2_after_num_bits", + "H41 stage2 after source num_bits", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"source_a_bits\":" + std::to_string(source_a_bits) + "}"); + // #endregion + } + if (power >= 12602010 && power <= 12602400) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H42", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h42_stage0_before_source_deref", + "H42 stage0 before source dereference", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + "}"); + // #endregion + form& source = forms[static_cast(pos)]; + const bool source_valid = source.check_valid(D); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H42", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h42_stage1_after_check_valid", + "H42 stage1 after check_valid", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"source_valid\":" + (source_valid ? "true" : "false") + "}"); + // #endregion + const uint64_t source_a_bits = static_cast(source.a.num_bits()); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H42", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h42_stage2_after_num_bits", + "H42 stage2 after source num_bits", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"source_a_bits\":" + std::to_string(source_a_bits) + "}"); + // #endregion + } + if (power >= 12642010 && power <= 12642400) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H43", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h43_stage0_before_source_deref", + "H43 stage0 before source dereference", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + "}"); + // #endregion + form& source = forms[static_cast(pos)]; + const uint64_t source_a_bits = static_cast(source.a.num_bits()); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H43", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h43_stage1_after_num_bits", + "H43 stage1 after source num_bits", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"source_a_bits\":" + std::to_string(source_a_bits) + "}"); + // #endregion + } + if (power >= 12500010 && power <= 12500600) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H44", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h44_stage0_before_source_deref", + "H44 stage0 before source dereference", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + "}"); + // #endregion + form& source = forms[static_cast(pos)]; + const uint64_t source_a_bits = static_cast(source.a.num_bits()); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H44", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h44_stage1_after_num_bits", + "H44 stage1 after source num_bits", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"source_a_bits\":" + std::to_string(source_a_bits) + "}"); + // #endregion + } + if (power >= 12607010 && power <= 12607600) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H45", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h45_stage0_before_source_deref", + "H45 stage0 before source dereference", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + "}"); + // #endregion + form& source = forms[static_cast(pos)]; + const uint64_t source_a_bits = static_cast(source.a.num_bits()); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H45", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h45_stage1_after_num_bits", + "H45 stage1 after source num_bits", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"source_a_bits\":" + std::to_string(source_a_bits) + "}"); + // #endregion + } + if (power >= 12500610 && power <= 12501200) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H46", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h46_stage0_before_source_deref", + "H46 stage0 before source dereference", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + "}"); + // #endregion + form& source = forms[static_cast(pos)]; + const uint64_t source_a_bits = static_cast(source.a.num_bits()); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H46", + "callback.h:TwoWesolowskiCallback:GetFormCopy_h46_stage1_after_num_bits", + "H46 stage1 after source num_bits", + std::string("{\"power\":") + std::to_string(power) + + ",\"pos\":" + std::to_string(pos) + + ",\"source_a_bits\":" + std::to_string(source_a_bits) + "}"); + // #endregion + } + return forms[static_cast(pos)]; } bool LargeConstants() { @@ -149,9 +830,65 @@ class TwoWesolowskiCallback: public WesolowskiCallback { void OnIteration(int type, void *data, uint64_t iteration) { iteration++; if (iteration % kl == 0) { - uint64_t pos = GetPosition(iteration); - form* mulf = &forms[pos]; + const int pos = GetPosition(iteration); + if (iteration >= 12647080 && iteration <= 12647220) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H39", + "callback.h:TwoWesolowskiCallback:OnIteration_h39_before_setform", + "H39 producer before SetForm", + std::string("{\"iteration\":") + std::to_string(iteration) + + ",\"pos\":" + std::to_string(pos) + + ",\"forms_capacity\":" + std::to_string(forms_capacity) + "}"); + // #endregion + } + if (iteration % 1000000 == 0) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H19", + "callback.h:TwoWesolowskiCallback:OnIteration_progress", + "OnIteration progress marker", + std::string("{\"iteration\":") + std::to_string(iteration) + + ",\"pos\":" + std::to_string(pos) + + ",\"forms_capacity\":" + std::to_string(forms_capacity) + + ",\"kl\":" + std::to_string(kl) + + ",\"switch_iters\":" + std::to_string(switch_iters) + "}"); + // #endregion + } + if (pos < 0 || static_cast(pos) >= forms_capacity) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H19", + "callback.h:TwoWesolowskiCallback:OnIteration_oob", + "OnIteration write position out of bounds", + std::string("{\"iteration\":") + std::to_string(iteration) + + ",\"pos\":" + std::to_string(pos) + + ",\"forms_capacity\":" + std::to_string(forms_capacity) + + ",\"kl\":" + std::to_string(kl) + + ",\"switch_iters\":" + std::to_string(switch_iters) + + ",\"switch_index\":" + std::to_string(switch_index) + "}"); + // #endregion + throw std::runtime_error("TwoWesolowskiCallback::OnIteration out of bounds"); + } + std::lock_guard lk(forms_mutex); + form* mulf = &forms[static_cast(pos)]; SetForm(type, data, mulf); + if (iteration >= 12647080 && iteration <= 12647220) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H39", + "callback.h:TwoWesolowskiCallback:OnIteration_h39_after_setform", + "H39 producer after SetForm", + std::string("{\"iteration\":") + std::to_string(iteration) + + ",\"pos\":" + std::to_string(pos) + + ",\"stored_valid\":" + (mulf->check_valid(D) ? "true" : "false") + + ",\"stored_a_bits\":" + std::to_string(mulf->a.num_bits()) + "}"); + // #endregion + } } } @@ -159,6 +896,7 @@ class TwoWesolowskiCallback: public WesolowskiCallback { uint64_t switch_index; int64_t switch_iters; uint32_t kl; + std::mutex forms_mutex; }; class FastAlgorithmCallback : public WesolowskiCallback { diff --git a/src/prover_base.hpp b/src/prover_base.hpp index e9758d59..7dbfe881 100644 --- a/src/prover_base.hpp +++ b/src/prover_base.hpp @@ -2,10 +2,82 @@ #define PROVER_BASE_H #include +#include +#include +#include +#include +#include #include "proof_common.h" #include "util.h" +inline const char* ProverAgentDebugLogPath() { + const char* env_path = std::getenv("CHIAVDF_AGENT_DEBUG_LOG"); + if (env_path != nullptr && env_path[0] != '\0') { + return env_path; + } + return "/Users/hoffmang/src/chiavdf/.cursor/debug.log"; +} + +inline bool ProverAgentDebugShouldMirror(const char* hypothesis_id) { + const char* mirror_all = std::getenv("CHIAVDF_AGENT_DEBUG_MIRROR_ALL"); + if (mirror_all != nullptr && mirror_all[0] == '1') { + return true; + } + return std::strcmp(hypothesis_id, "H14") == 0 || + std::strcmp(hypothesis_id, "H16") == 0 || + std::strcmp(hypothesis_id, "H18") == 0 || + std::strcmp(hypothesis_id, "H19") == 0 || + std::strcmp(hypothesis_id, "H22") == 0 || + std::strcmp(hypothesis_id, "H28") == 0 || + std::strcmp(hypothesis_id, "H29") == 0 || + std::strcmp(hypothesis_id, "H32") == 0 || + std::strcmp(hypothesis_id, "H33") == 0 || + std::strcmp(hypothesis_id, "H34") == 0 || + std::strcmp(hypothesis_id, "H35") == 0 || + std::strcmp(hypothesis_id, "H36") == 0 || + std::strcmp(hypothesis_id, "H38") == 0 || + std::strcmp(hypothesis_id, "H40") == 0 || + std::strcmp(hypothesis_id, "H41") == 0 || + std::strcmp(hypothesis_id, "H42") == 0 || + std::strcmp(hypothesis_id, "H43") == 0 || + std::strcmp(hypothesis_id, "H44") == 0 || + std::strcmp(hypothesis_id, "H45") == 0 || + std::strcmp(hypothesis_id, "H46") == 0 || + std::strcmp(hypothesis_id, "H52") == 0; +} + +inline void ProverAgentDebugLog(const char* run_id, const char* hypothesis_id, const char* location, const char* message, const std::string& data_json) { + static std::atomic seq{0}; + std::ofstream out(ProverAgentDebugLogPath(), std::ios::app); + if (!out.is_open()) { + return; + } + const auto ts = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); + const uint64_t id = ++seq; + out << "{\"id\":\"log_" << ts << "_" << id + << "\",\"timestamp\":" << ts + << ",\"runId\":\"" << run_id + << "\",\"hypothesisId\":\"" << hypothesis_id + << "\",\"location\":\"" << location + << "\",\"message\":\"" << message + << "\",\"data\":" << data_json + << "}\n"; + if (ProverAgentDebugShouldMirror(hypothesis_id)) { + std::cerr << "AGENTLOG " + << "{\"id\":\"log_" << ts << "_" << id + << "\",\"timestamp\":" << ts + << ",\"runId\":\"" << run_id + << "\",\"hypothesisId\":\"" << hypothesis_id + << "\",\"location\":\"" << location + << "\",\"message\":\"" << message + << "\",\"data\":" << data_json + << "}\n"; + } +} + class Prover { public: Prover(Segment segm, integer D) { @@ -38,6 +110,18 @@ class Prover { } void GenerateProof() { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H15", + "prover_base.hpp:Prover:GenerateProof_enter", + "GenerateProof enter", + std::string("{\"num_iterations\":") + std::to_string(num_iterations) + + ",\"k\":" + std::to_string(k) + + ",\"l\":" + std::to_string(l) + + ",\"seg_start\":" + std::to_string(segm.start) + + ",\"seg_length\":" + std::to_string(segm.length) + "}"); + // #endregion PulmarkReducer reducer; integer B = GetB(D, segm.x, segm.y); @@ -54,6 +138,14 @@ class Prover { return ; } + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H15", + "prover_base.hpp:Prover:GenerateProof_after_identity", + "Identity setup complete", + "{}"); + // #endregion uint64_t k1 = k / 2; uint64_t k0 = k - k1; form x = id; @@ -69,16 +161,1171 @@ class Prover { uint64_t limit = num_iterations / (k * l); if (num_iterations % (k * l)) limit++; + // #region agent log + if (j == static_cast(l - 1)) { + ProverAgentDebugLog( + "post-fix", + "H15", + "prover_base.hpp:Prover:GenerateProof_first_round", + "First outer round setup", + std::string("{\"j\":") + std::to_string(j) + + ",\"limit\":" + std::to_string(limit) + "}"); + } + // #endregion for (uint64_t i = 0; i < limit; i++) { if (num_iterations >= k * (i * l + j + 1)) { + if (segm.start >= 10000000 && j == 0 && i >= 264300 && i <= 264700) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H33", + "prover_base.hpp:Prover:GenerateProof_boundary_iter_enter", + "Boundary window iteration enter", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"limit\":" + std::to_string(limit) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264430 && i <= 264432) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H34", + "prover_base.hpp:Prover:GenerateProof_iter_before_getblock", + "Focused window before GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264701 && i <= 264760) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H35", + "prover_base.hpp:Prover:GenerateProof_post700_before_getblock", + "Post-264700 focused window before GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 269980 && i <= 270060) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H36", + "prover_base.hpp:Prover:GenerateProof_270k_before_getblock", + "270k window before GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264318 && i <= 264324) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H38", + "prover_base.hpp:Prover:GenerateProof_crash_window_before_getblock", + "Crash-window before GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264410 && i <= 264430) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H40", + "prover_base.hpp:Prover:GenerateProof_h40_before_getblock", + "H40 window before GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 263500 && i <= 263520) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H41", + "prover_base.hpp:Prover:GenerateProof_h41_before_getblock", + "H41 window before GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260201 && i <= 260240) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H42", + "prover_base.hpp:Prover:GenerateProof_h42_before_getblock", + "H42 micro window before GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264201 && i <= 264240) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H43", + "prover_base.hpp:Prover:GenerateProof_h43_before_getblock", + "H43 micro window before GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 250001 && i <= 250060) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H44", + "prover_base.hpp:Prover:GenerateProof_h44_before_getblock", + "H44 micro window before GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260701 && i <= 260760) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H45", + "prover_base.hpp:Prover:GenerateProof_h45_before_getblock", + "H45 micro window before GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 250061 && i <= 250120) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H46", + "prover_base.hpp:Prover:GenerateProof_h46_before_getblock", + "H46 micro window before GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260000 && i <= 265000 && (i % 100 == 0)) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H29", + "prover_base.hpp:Prover:GenerateProof_tail_before_getblock", + "Tail window before GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"num_iterations\":" + std::to_string(num_iterations) + "}"); + // #endregion + } uint64_t b = GetBlock(i*l + j, k, num_iterations, B); + if (segm.start >= 10000000 && j == 0 && i >= 264430 && i <= 264432) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H34", + "prover_base.hpp:Prover:GenerateProof_iter_after_getblock", + "Focused window after GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264701 && i <= 264760) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H35", + "prover_base.hpp:Prover:GenerateProof_post700_after_getblock", + "Post-264700 focused window after GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 269980 && i <= 270060) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H36", + "prover_base.hpp:Prover:GenerateProof_270k_after_getblock", + "270k window after GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264318 && i <= 264324) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H38", + "prover_base.hpp:Prover:GenerateProof_crash_window_after_getblock", + "Crash-window after GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264410 && i <= 264430) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H40", + "prover_base.hpp:Prover:GenerateProof_h40_after_getblock", + "H40 window after GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 263500 && i <= 263520) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H41", + "prover_base.hpp:Prover:GenerateProof_h41_after_getblock", + "H41 window after GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260201 && i <= 260240) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H42", + "prover_base.hpp:Prover:GenerateProof_h42_after_getblock", + "H42 micro window after GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264201 && i <= 264240) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H43", + "prover_base.hpp:Prover:GenerateProof_h43_after_getblock", + "H43 micro window after GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 250001 && i <= 250060) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H44", + "prover_base.hpp:Prover:GenerateProof_h44_after_getblock", + "H44 micro window after GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260701 && i <= 260760) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H45", + "prover_base.hpp:Prover:GenerateProof_h45_after_getblock", + "H45 micro window after GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 250061 && i <= 250120) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H46", + "prover_base.hpp:Prover:GenerateProof_h46_after_getblock", + "H46 micro window after GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 265001 && i <= 265200) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H30", + "prover_base.hpp:Prover:GenerateProof_micro_after_getblock", + "Micro window after GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260000 && i <= 265000 && (i % 100 == 0)) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H29", + "prover_base.hpp:Prover:GenerateProof_tail_after_getblock", + "Tail window after GetBlock", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + if (b >= (1UL << k)) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H18", + "prover_base.hpp:Prover:GenerateProof_block_oob", + "Computed block index out of bounds", + std::string("{\"b\":") + std::to_string(b) + + ",\"k\":" + std::to_string(k) + + ",\"i\":" + std::to_string(i) + + ",\"j\":" + std::to_string(j) + + ",\"num_iterations\":" + std::to_string(num_iterations) + "}"); + // #endregion + throw std::runtime_error("GenerateProof block index out of bounds"); + } if (!PerformExtraStep()) return; + if (segm.start >= 10000000 && j == 0 && i >= 265001 && i <= 265200) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H30", + "prover_base.hpp:Prover:GenerateProof_micro_after_extra_step", + "Micro window after PerformExtraStep", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260000 && i <= 265000 && (i % 100 == 0)) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H28", + "prover_base.hpp:Prover:GenerateProof_tail_before_getform", + "Tail window before GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && (i % 50000 == 0)) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H24", + "prover_base.hpp:Prover:GenerateProof_progress_before_getform", + "Long GenerateProof progress before GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"limit\":" + std::to_string(limit) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + // #region agent log + if (j == static_cast(l - 1) && i == 0) { + ProverAgentDebugLog( + "post-fix", + "H15", + "prover_base.hpp:Prover:GenerateProof_before_first_getform", + "About to fetch first intermediate form", + std::string("{\"block\":") + std::to_string(b) + "}"); + } + // #endregion + if (segm.start >= 10000000 && j == 0 && i >= 265001 && i <= 265200) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H32", + "prover_base.hpp:Prover:GenerateProof_micro_before_getform_call", + "Micro window immediately before GetForm call", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264430 && i <= 264432) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H34", + "prover_base.hpp:Prover:GenerateProof_iter_before_getform", + "Focused window before GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264701 && i <= 264760) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H35", + "prover_base.hpp:Prover:GenerateProof_post700_before_getform", + "Post-264700 focused window before GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 269980 && i <= 270060) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H36", + "prover_base.hpp:Prover:GenerateProof_270k_before_getform", + "270k window before GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264318 && i <= 264324) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H38", + "prover_base.hpp:Prover:GenerateProof_crash_window_before_getform", + "Crash-window before GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264410 && i <= 264430) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H40", + "prover_base.hpp:Prover:GenerateProof_h40_before_getform", + "H40 window before GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260201 && i <= 260240) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H42", + "prover_base.hpp:Prover:GenerateProof_h42_before_getform", + "H42 micro window before GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264201 && i <= 264240) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H43", + "prover_base.hpp:Prover:GenerateProof_h43_before_getform", + "H43 micro window before GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 250001 && i <= 250060) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H44", + "prover_base.hpp:Prover:GenerateProof_h44_before_getform", + "H44 micro window before GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260701 && i <= 260760) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H45", + "prover_base.hpp:Prover:GenerateProof_h45_before_getform", + "H45 micro window before GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 250061 && i <= 250120) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H46", + "prover_base.hpp:Prover:GenerateProof_h46_before_getform", + "H46 micro window before GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 230000 && i <= 230200) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H52", + "prover_base.hpp:Prover:GenerateProof_h52_before_getform", + "H52 focused window before GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } tmp = GetForm(i); + if (segm.start >= 10000000 && j == 0 && i >= 264430 && i <= 264432) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H34", + "prover_base.hpp:Prover:GenerateProof_iter_after_getform", + "Focused window after GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + + ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264701 && i <= 264760) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H35", + "prover_base.hpp:Prover:GenerateProof_post700_after_getform", + "Post-264700 focused window after GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + + ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 269980 && i <= 270060) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H36", + "prover_base.hpp:Prover:GenerateProof_270k_after_getform", + "270k window after GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + + ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264318 && i <= 264324) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H38", + "prover_base.hpp:Prover:GenerateProof_crash_window_after_getform", + "Crash-window after GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + + ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264410 && i <= 264430) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H40", + "prover_base.hpp:Prover:GenerateProof_h40_after_getform", + "H40 window after GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + + ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260201 && i <= 260240) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H42", + "prover_base.hpp:Prover:GenerateProof_h42_after_getform", + "H42 micro window after GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + + ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264201 && i <= 264240) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H43", + "prover_base.hpp:Prover:GenerateProof_h43_after_getform", + "H43 micro window after GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + + ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 250001 && i <= 250060) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H44", + "prover_base.hpp:Prover:GenerateProof_h44_after_getform", + "H44 micro window after GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + + ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260701 && i <= 260760) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H45", + "prover_base.hpp:Prover:GenerateProof_h45_after_getform", + "H45 micro window after GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + + ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 250061 && i <= 250120) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H46", + "prover_base.hpp:Prover:GenerateProof_h46_after_getform", + "H46 micro window after GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + + ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 230000 && i <= 230200) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H52", + "prover_base.hpp:Prover:GenerateProof_h52_after_getform", + "H52 focused window after GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + + ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 265001 && i <= 265200) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H30", + "prover_base.hpp:Prover:GenerateProof_micro_after_getform", + "Micro window after GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260000 && i <= 265000 && (i % 100 == 0)) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H28", + "prover_base.hpp:Prover:GenerateProof_tail_after_getform", + "Tail window after GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && (i % 50000 == 0)) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H24", + "prover_base.hpp:Prover:GenerateProof_progress_after_getform", + "Long GenerateProof progress after GetForm", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + // #region agent log + if (j == static_cast(l - 1) && i == 0) { + ProverAgentDebugLog( + "post-fix", + "H15", + "prover_base.hpp:Prover:GenerateProof_after_first_getform", + "Fetched first intermediate form", + "{}"); + } + // #endregion + if (segm.start >= 10000000 && j == 0 && (i % 10000 == 0)) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H26", + "prover_base.hpp:Prover:GenerateProof_before_nucomp_fine", + "Fine-grained long GenerateProof before nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + + ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + + ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260000 && i <= 265000 && (i % 100 == 0)) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H28", + "prover_base.hpp:Prover:GenerateProof_tail_before_nucomp", + "Tail window before nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264430 && i <= 264432) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H34", + "prover_base.hpp:Prover:GenerateProof_iter_before_nucomp", + "Focused window before nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264701 && i <= 264760) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H35", + "prover_base.hpp:Prover:GenerateProof_post700_before_nucomp", + "Post-264700 focused window before nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 269980 && i <= 270060) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H36", + "prover_base.hpp:Prover:GenerateProof_270k_before_nucomp", + "270k window before nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264318 && i <= 264324) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H38", + "prover_base.hpp:Prover:GenerateProof_crash_window_before_nucomp", + "Crash-window before nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264410 && i <= 264430) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H40", + "prover_base.hpp:Prover:GenerateProof_h40_before_nucomp", + "H40 window before nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260201 && i <= 260240) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H42", + "prover_base.hpp:Prover:GenerateProof_h42_before_nucomp", + "H42 micro window before nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264201 && i <= 264240) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H43", + "prover_base.hpp:Prover:GenerateProof_h43_before_nucomp", + "H43 micro window before nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 250001 && i <= 250060) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H44", + "prover_base.hpp:Prover:GenerateProof_h44_before_nucomp", + "H44 micro window before nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260701 && i <= 260760) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H45", + "prover_base.hpp:Prover:GenerateProof_h45_before_nucomp", + "H45 micro window before nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 250061 && i <= 250120) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H46", + "prover_base.hpp:Prover:GenerateProof_h46_before_nucomp", + "H46 micro window before nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); + // #endregion + } nucomp_form(ys[b], ys[b], *tmp, D, L); + if (segm.start >= 10000000 && j == 0 && i >= 264430 && i <= 264432) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H34", + "prover_base.hpp:Prover:GenerateProof_iter_after_nucomp", + "Focused window after nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 230000 && i <= 230200) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H52", + "prover_base.hpp:Prover:GenerateProof_h52_after_nucomp", + "H52 focused window after nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264701 && i <= 264760) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H35", + "prover_base.hpp:Prover:GenerateProof_post700_after_nucomp", + "Post-264700 focused window after nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 269980 && i <= 270060) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H36", + "prover_base.hpp:Prover:GenerateProof_270k_after_nucomp", + "270k window after nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264318 && i <= 264324) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H38", + "prover_base.hpp:Prover:GenerateProof_crash_window_after_nucomp", + "Crash-window after nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264410 && i <= 264430) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H40", + "prover_base.hpp:Prover:GenerateProof_h40_after_nucomp", + "H40 window after nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 263500 && i <= 263520) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H41", + "prover_base.hpp:Prover:GenerateProof_h41_after_nucomp", + "H41 window after nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260201 && i <= 260240) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H42", + "prover_base.hpp:Prover:GenerateProof_h42_after_nucomp", + "H42 micro window after nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264201 && i <= 264240) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H43", + "prover_base.hpp:Prover:GenerateProof_h43_after_nucomp", + "H43 micro window after nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 250001 && i <= 250060) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H44", + "prover_base.hpp:Prover:GenerateProof_h44_after_nucomp", + "H44 micro window after nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260701 && i <= 260760) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H45", + "prover_base.hpp:Prover:GenerateProof_h45_after_nucomp", + "H45 micro window after nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 250061 && i <= 250120) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H46", + "prover_base.hpp:Prover:GenerateProof_h46_after_nucomp", + "H46 micro window after nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 265001 && i <= 265200) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H30", + "prover_base.hpp:Prover:GenerateProof_micro_after_nucomp", + "Micro window after nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260000 && i <= 265000 && (i % 100 == 0)) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H28", + "prover_base.hpp:Prover:GenerateProof_tail_after_nucomp", + "Tail window after nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && (i % 10000 == 0)) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H26", + "prover_base.hpp:Prover:GenerateProof_after_nucomp_fine", + "Fine-grained long GenerateProof after nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && (i % 50000 == 0)) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H24", + "prover_base.hpp:Prover:GenerateProof_progress_after_nucomp", + "Long GenerateProof progress after nucomp_form", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"b\":" + std::to_string(b) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 260000 && (i % 5000 == 0)) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H27", + "prover_base.hpp:Prover:GenerateProof_tail_progress", + "Long GenerateProof tail progress marker", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"limit\":" + std::to_string(limit) + "}"); + // #endregion + } + if (segm.start >= 10000000 && j == 0 && i >= 264300 && i <= 264700) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H33", + "prover_base.hpp:Prover:GenerateProof_boundary_iter_exit", + "Boundary window iteration exit", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"i\":" + std::to_string(i) + + ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + + ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); + // #endregion + } } } + if (segm.start >= 10000000 && j == 0) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H27", + "prover_base.hpp:Prover:GenerateProof_after_collect_phase", + "Completed long GenerateProof collect phase", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"limit\":" + std::to_string(limit) + "}"); + // #endregion + } for (uint64_t b1 = 0; b1 < (1UL << k1); b1++) { + if (segm.start >= 10000000 && j == 0 && (b1 % 16 == 0)) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H27", + "prover_base.hpp:Prover:GenerateProof_phase2_progress", + "Long GenerateProof phase2 progress", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"b1\":" + std::to_string(b1) + "}"); + // #endregion + } form z = id; for (uint64_t b0 = 0; b0 < (1UL << k0); b0++) { if (!PerformExtraStep()) return; @@ -87,8 +1334,29 @@ class Prover { z = FastPowFormNucomp(z, D, integer(b1 * (1 << k0)), L, reducer); nucomp_form(x, x, z, D, L); } + if (segm.start >= 10000000 && j == 0) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H27", + "prover_base.hpp:Prover:GenerateProof_after_phase2", + "Completed long GenerateProof phase2", + std::string("{\"seg_start\":") + std::to_string(segm.start) + "}"); + // #endregion + } for (uint64_t b0 = 0; b0 < (1UL << k0); b0++) { + if (segm.start >= 10000000 && j == 0 && (b0 % 16 == 0)) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H27", + "prover_base.hpp:Prover:GenerateProof_phase3_progress", + "Long GenerateProof phase3 progress", + std::string("{\"seg_start\":") + std::to_string(segm.start) + + ",\"b0\":" + std::to_string(b0) + "}"); + // #endregion + } form z = id; for (uint64_t b1 = 0; b1 < (1UL << k1); b1++) { if (!PerformExtraStep()) return; @@ -97,10 +1365,28 @@ class Prover { z = FastPowFormNucomp(z, D, integer(b0), L, reducer); nucomp_form(x, x, z, D, L); } + if (segm.start >= 10000000 && j == 0) { + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H27", + "prover_base.hpp:Prover:GenerateProof_after_phase3", + "Completed long GenerateProof phase3", + std::string("{\"seg_start\":") + std::to_string(segm.start) + "}"); + // #endregion + } } reducer.reduce(x); proof = x; OnFinish(); + // #region agent log + ProverAgentDebugLog( + "post-fix", + "H15", + "prover_base.hpp:Prover:GenerateProof_exit", + "GenerateProof finished", + "{}"); + // #endregion } protected: diff --git a/src/provers.h b/src/provers.h index 11209345..839d6843 100644 --- a/src/provers.h +++ b/src/provers.h @@ -54,12 +54,523 @@ class TwoWesolowskiProver : public Prover{ } void start() { - std::thread t([=] { GenerateProof(); }); - t.detach(); + // #region agent log + CallbackAgentDebugLog("post-fix", "H14", "provers.h:TwoWesolowskiProver:start_enter", "TwoWesolowskiProver start called", "{}"); + // #endregion + try { + std::thread t([=] { GenerateProof(); }); + t.detach(); + // #region agent log + CallbackAgentDebugLog("post-fix", "H14", "provers.h:TwoWesolowskiProver:start_detached", "Prover thread created and detached", "{}"); + // #endregion + } catch (const std::system_error& e) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H14", + "provers.h:TwoWesolowskiProver:start_fallback_inline", + "Thread creation failed, running inline", + std::string("{\"what\":\"") + e.what() + "\"}"); + // #endregion + GenerateProof(); + } } virtual form* GetForm(uint64_t i) { - return weso->GetForm(done_iterations + i * k * l); + const uint64_t power = done_iterations + i * k * l; + const int64_t produced = weso->iterations.load(std::memory_order_relaxed); + if (done_iterations >= 10000000 && (i % 50000 == 0)) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H25", + "provers.h:TwoWesolowskiProver:GetForm_progress", + "Long prover GetForm progress", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + + ",\"k\":" + std::to_string(k) + + ",\"l\":" + std::to_string(l) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 260000 && i <= 265000 && (i % 100 == 0)) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H29", + "provers.h:TwoWesolowskiProver:GetForm_tail_window", + "Tail window prover GetForm details", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + + ",\"k\":" + std::to_string(k) + + ",\"l\":" + std::to_string(l) + "}"); + // #endregion + } + if (power > static_cast(produced)) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H22", + "provers.h:TwoWesolowskiProver:GetForm_read_ahead", + "Requested form ahead of produced iterations", + std::string("{\"power\":") + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + + ",\"done_iterations\":" + std::to_string(done_iterations) + + ",\"k\":" + std::to_string(k) + + ",\"l\":" + std::to_string(l) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 265001 && i <= 265200) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H30", + "provers.h:TwoWesolowskiProver:GetForm_micro_before_copy", + "Micro window before GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 264430 && i <= 264432) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H34", + "provers.h:TwoWesolowskiProver:GetForm_focused_before_copy", + "Focused window before GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 264701 && i <= 264760) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H35", + "provers.h:TwoWesolowskiProver:GetForm_post700_before_copy", + "Post-264700 focused window before GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 269980 && i <= 270060) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H36", + "provers.h:TwoWesolowskiProver:GetForm_270k_before_copy", + "270k window before GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 264318 && i <= 264324) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H38", + "provers.h:TwoWesolowskiProver:GetForm_crash_window_before_copy", + "Crash-window before GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 264410 && i <= 264430) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H40", + "provers.h:TwoWesolowskiProver:GetForm_h40_before_copy", + "H40 window before GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 263500 && i <= 263520) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H41", + "provers.h:TwoWesolowskiProver:GetForm_h41_before_copy", + "H41 window before GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 260201 && i <= 260240) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H42", + "provers.h:TwoWesolowskiProver:GetForm_h42_before_copy", + "H42 micro window before GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 264201 && i <= 264240) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H43", + "provers.h:TwoWesolowskiProver:GetForm_h43_before_copy", + "H43 micro window before GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 250001 && i <= 250060) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H44", + "provers.h:TwoWesolowskiProver:GetForm_h44_before_copy", + "H44 micro window before GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 260701 && i <= 260760) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H45", + "provers.h:TwoWesolowskiProver:GetForm_h45_before_copy", + "H45 micro window before GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 250061 && i <= 250120) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H46", + "provers.h:TwoWesolowskiProver:GetForm_h46_before_copy", + "H46 micro window before GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 250058 && i <= 250062) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H47", + "provers.h:TwoWesolowskiProver:GetForm_h47_before_copy", + "H47 tight boundary before GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 250090 && i <= 250100) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H50", + "provers.h:TwoWesolowskiProver:GetForm_h50_before_copy", + "H50 boundary before GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 250061 && i <= 250063) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H51", + "provers.h:TwoWesolowskiProver:GetForm_h51_before_copy", + "H51 boundary before GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 250030 && i <= 250040) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H49", + "provers.h:TwoWesolowskiProver:GetForm_h49_before_copy", + "H49 boundary before GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"produced_iterations\":" + std::to_string(produced) + + ",\"weso_ptr\":" + + std::to_string(static_cast(reinterpret_cast(weso))) + "}"); + // #endregion + } + cached_form = weso->GetFormCopy(power); + if (done_iterations >= 10000000 && i >= 264430 && i <= 264432) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H34", + "provers.h:TwoWesolowskiProver:GetForm_focused_after_copy", + "Focused window after GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + + ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 264701 && i <= 264760) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H35", + "provers.h:TwoWesolowskiProver:GetForm_post700_after_copy", + "Post-264700 focused window after GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + + ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 269980 && i <= 270060) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H36", + "provers.h:TwoWesolowskiProver:GetForm_270k_after_copy", + "270k window after GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + + ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 264410 && i <= 264430) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H40", + "provers.h:TwoWesolowskiProver:GetForm_h40_after_copy", + "H40 window after GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + + ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 264318 && i <= 264324) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H38", + "provers.h:TwoWesolowskiProver:GetForm_crash_window_after_copy", + "Crash-window after GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + + ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 263500 && i <= 263520) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H41", + "provers.h:TwoWesolowskiProver:GetForm_h41_after_copy", + "H41 window after GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + + ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 260201 && i <= 260240) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H42", + "provers.h:TwoWesolowskiProver:GetForm_h42_after_copy", + "H42 micro window after GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + + ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 264201 && i <= 264240) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H43", + "provers.h:TwoWesolowskiProver:GetForm_h43_after_copy", + "H43 micro window after GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + + ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 250001 && i <= 250060) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H44", + "provers.h:TwoWesolowskiProver:GetForm_h44_after_copy", + "H44 micro window after GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + + ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 260701 && i <= 260760) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H45", + "provers.h:TwoWesolowskiProver:GetForm_h45_after_copy", + "H45 micro window after GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + + ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 250061 && i <= 250120) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H46", + "provers.h:TwoWesolowskiProver:GetForm_h46_after_copy", + "H46 micro window after GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + + ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 250058 && i <= 250062) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H47", + "provers.h:TwoWesolowskiProver:GetForm_h47_after_copy", + "H47 tight boundary after GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + + ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 250090 && i <= 250100) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H50", + "provers.h:TwoWesolowskiProver:GetForm_h50_after_copy", + "H50 boundary after GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + + ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 250061 && i <= 250063) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H51", + "provers.h:TwoWesolowskiProver:GetForm_h51_after_copy", + "H51 boundary after GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + + ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 250030 && i <= 250040) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H49", + "provers.h:TwoWesolowskiProver:GetForm_h49_after_copy", + "H49 boundary after GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + + ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 265001 && i <= 265200) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H30", + "provers.h:TwoWesolowskiProver:GetForm_micro_after_copy", + "Micro window after GetFormCopy", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + "}"); + // #endregion + } + if (done_iterations >= 10000000 && i >= 265001 && i <= 265200) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H32", + "provers.h:TwoWesolowskiProver:GetForm_micro_before_return", + "Micro window before returning cached form pointer", + std::string("{\"done_iterations\":") + std::to_string(done_iterations) + + ",\"i\":" + std::to_string(i) + + ",\"power\":" + std::to_string(power) + + ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + + ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); + // #endregion + } + return &cached_form; } void stop() { @@ -77,6 +588,7 @@ class TwoWesolowskiProver : public Prover{ TwoWesolowskiCallback* weso; std::atomic& stop_signal; uint64_t done_iterations; + form cached_form; }; extern bool new_event; diff --git a/src/vdf.h b/src/vdf.h index 42f41d14..af9673cb 100644 --- a/src/vdf.h +++ b/src/vdf.h @@ -131,25 +131,127 @@ static inline void repeated_square_nudupl( fallback_reducer.emplace(); } for (uint64_t i = 0; i < iterations; i++) { + const uint64_t current_iter = base + i + 1; + if (two_weso && current_iter >= 13860000 && current_iter <= 13920000 && (current_iter % 500 == 0)) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H33", + "vdf.h:repeated_square_nudupl:before_nudupl", + "NUDUPL worker micro window before nudupl_form", + std::string("{\"current_iter\":") + std::to_string(current_iter) + "}"); + // #endregion + } + if (two_weso && current_iter >= 13891000 && current_iter <= 13893000 && (current_iter % 100 == 0)) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H35", + "vdf.h:repeated_square_nudupl:post700_before_nudupl", + "Post-13891000 focused worker window before nudupl_form", + std::string("{\"current_iter\":") + std::to_string(current_iter) + "}"); + // #endregion + } + if (two_weso && current_iter >= 13885500 && current_iter <= 13887500 && (current_iter % 100 == 0)) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H36", + "vdf.h:repeated_square_nudupl:270k_before_nudupl", + "270k-correlated worker window before nudupl_form", + std::string("{\"current_iter\":") + std::to_string(current_iter) + "}"); + // #endregion + } nudupl_form(f, f, D, L); + if (two_weso && current_iter >= 13860000 && current_iter <= 13920000 && (current_iter % 500 == 0)) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H33", + "vdf.h:repeated_square_nudupl:after_nudupl", + "NUDUPL worker micro window after nudupl_form", + std::string("{\"current_iter\":") + std::to_string(current_iter) + "}"); + // #endregion + } + if (two_weso && current_iter >= 13891000 && current_iter <= 13893000 && (current_iter % 100 == 0)) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H35", + "vdf.h:repeated_square_nudupl:post700_after_nudupl", + "Post-13891000 focused worker window after nudupl_form", + std::string("{\"current_iter\":") + std::to_string(current_iter) + "}"); + // #endregion + } + if (two_weso && current_iter >= 13885500 && current_iter <= 13887500 && (current_iter % 100 == 0)) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H36", + "vdf.h:repeated_square_nudupl:270k_after_nudupl", + "270k-correlated worker window after nudupl_form", + std::string("{\"current_iter\":") + std::to_string(current_iter) + "}"); + // #endregion + } // Reduce only when `a` grows beyond a small limb threshold. Reducing every iteration // can be slower than letting NUDUPL run a bit "wide". if (__GMP_ABS(f.a.impl->_mp_size) > 8) { + if (two_weso && current_iter >= 13885500 && current_iter <= 13887500 && (current_iter % 100 == 0)) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H36", + "vdf.h:repeated_square_nudupl:270k_before_reduce", + "270k-correlated worker window before reduce", + std::string("{\"current_iter\":") + std::to_string(current_iter) + + ",\"a_limb_size\":" + std::to_string(__GMP_ABS(f.a.impl->_mp_size)) + "}"); + // #endregion + } if (weso) { weso->reduce(f); } else { fallback_reducer->reduce(f); } + if (two_weso && current_iter >= 13885500 && current_iter <= 13887500 && (current_iter % 100 == 0)) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H36", + "vdf.h:repeated_square_nudupl:270k_after_reduce", + "270k-correlated worker window after reduce", + std::string("{\"current_iter\":") + std::to_string(current_iter) + "}"); + // #endregion + } } if (nuduplListener != nullptr) { + if (two_weso && current_iter >= 13885500 && current_iter <= 13887500 && (current_iter % 100 == 0)) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H36", + "vdf.h:repeated_square_nudupl:270k_before_oniteration", + "270k-correlated worker window before OnIteration callback", + std::string("{\"current_iter\":") + std::to_string(current_iter) + "}"); + // #endregion + } // Present the C++ `form` as a `vdf_original::form` view so existing callbacks can // consume it without any new type tags. f_view.a[0] = f.a.impl[0]; f_view.b[0] = f.b.impl[0]; f_view.c[0] = f.c.impl[0]; nuduplListener->OnIteration(NL_FORM, &f_view, base + i); + if (two_weso && current_iter >= 13885500 && current_iter <= 13887500 && (current_iter % 100 == 0)) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H36", + "vdf.h:repeated_square_nudupl:270k_after_oniteration", + "270k-correlated worker window after OnIteration callback", + std::string("{\"current_iter\":") + std::to_string(current_iter) + "}"); + // #endregion + } } } } @@ -166,6 +268,8 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege uint64_t num_iterations = 0; uint64_t last_checkpoint = 0; + uint64_t debug_progress_mark = 12000000; + uint64_t debug_fast_call_mark = 13500000; while (!stopped) { uint64 c_checkpoint_interval=checkpoint_interval; @@ -197,7 +301,30 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege // x86/x64: use the phased pipeline. square_state_type square_state; square_state.pairindex = 0; + if (two_weso && num_iterations >= debug_fast_call_mark) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H21", + "vdf.h:repeated_square:before_fast_call", + "About to call repeated_square_fast", + std::string("{\"num_iterations\":") + std::to_string(num_iterations) + + ",\"batch_size\":" + std::to_string(batch_size) + "}"); + // #endregion + } actual_iterations = repeated_square_fast(square_state, f, D, L, num_iterations, batch_size, weso); + if (two_weso && num_iterations >= debug_fast_call_mark) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H21", + "vdf.h:repeated_square:after_fast_call", + "repeated_square_fast returned", + std::string("{\"num_iterations\":") + std::to_string(num_iterations) + + ",\"actual_iterations\":" + std::to_string(actual_iterations) + "}"); + // #endregion + debug_fast_call_mark += 100000; + } #else // Non-x86: use the C++ NUDUPL path (faster and lower maintenance than the phased pipeline). integer& D_nc = const_cast(D); @@ -248,6 +375,19 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege } num_iterations+=actual_iterations; + if (two_weso && num_iterations >= debug_progress_mark) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H20", + "vdf.h:repeated_square:progress", + "repeated_square progress marker", + std::string("{\"num_iterations\":") + std::to_string(num_iterations) + + ",\"actual_iterations\":" + std::to_string(actual_iterations) + + ",\"batch_size\":" + std::to_string(batch_size) + "}"); + // #endregion + debug_progress_mark += 500000; + } if (num_iterations >= last_checkpoint) { weso->iterations = num_iterations; @@ -351,17 +491,59 @@ Proof ProveOneWesolowski(uint64_t iters, integer& D, form f, OneWesolowskiCallba Proof ProveTwoWeso(integer& D, form x, uint64_t iters, uint64_t done_iterations, TwoWesolowskiCallback* weso, int depth, std::atomic& stop_signal) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H17", + "vdf.h:ProveTwoWeso:enter", + "Enter ProveTwoWeso", + std::string("{\"depth\":") + std::to_string(depth) + + ",\"iters\":" + std::to_string(iters) + + ",\"done_iterations\":" + std::to_string(done_iterations) + "}"); + // #endregion integer L=root(-D, 4); if (depth == 2) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H17", + "vdf.h:ProveTwoWeso:depth2_before_wait", + "Depth-2 waiting for required iterations", + std::string("{\"target\":") + std::to_string(done_iterations + iters) + "}"); + // #endregion while (!stop_signal && weso->iterations < done_iterations + iters) { std::this_thread::sleep_for (std::chrono::milliseconds(200)); } + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H17", + "vdf.h:ProveTwoWeso:depth2_after_wait", + "Depth-2 wait completed", + std::string("{\"iterations_now\":") + std::to_string(weso->iterations.load()) + "}"); + // #endregion if (stop_signal) return Proof(); vdf_original vdfo_proof; uint64 checkpoint = (done_iterations + iters) - (done_iterations + iters) % 100; - form y = *(weso->GetForm(checkpoint)); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H17", + "vdf.h:ProveTwoWeso:depth2_before_checkpoint_get", + "Depth-2 loading checkpoint form", + std::string("{\"checkpoint\":") + std::to_string(checkpoint) + "}"); + // #endregion + form y = weso->GetFormCopy(checkpoint); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H17", + "vdf.h:ProveTwoWeso:depth2_after_checkpoint_get", + "Depth-2 loaded checkpoint form", + "{}"); + // #endregion repeated_square_original(vdfo_proof, y, D, L, 0, (done_iterations + iters) % 100, NULL); Segment sg( @@ -371,7 +553,23 @@ Proof ProveTwoWeso(integer& D, form x, uint64_t iters, uint64_t done_iterations, /*y=*/y ); TwoWesolowskiProver prover(sg, D, weso, stop_signal); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H17", + "vdf.h:ProveTwoWeso:depth2_before_generate", + "Depth-2 prover GenerateProof start", + "{}"); + // #endregion prover.GenerateProof(); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H17", + "vdf.h:ProveTwoWeso:depth2_after_generate", + "Depth-2 prover GenerateProof finished", + "{}"); + // #endregion if (stop_signal) return Proof(); @@ -394,7 +592,7 @@ Proof ProveTwoWeso(integer& D, form x, uint64_t iters, uint64_t done_iterations, if (stop_signal) return Proof(); - form y1 = *(weso->GetForm(done_iterations + iterations1)); + form y1 = weso->GetFormCopy(done_iterations + iterations1); Segment sg( /*start=*/done_iterations, /*lenght=*/iterations1, @@ -403,10 +601,42 @@ Proof ProveTwoWeso(integer& D, form x, uint64_t iters, uint64_t done_iterations, ); TwoWesolowskiProver prover(sg, D, weso, stop_signal); prover.start(); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H17", + "vdf.h:ProveTwoWeso:before_recursive_call", + "Calling recursive ProveTwoWeso", + std::string("{\"next_depth\":") + std::to_string(depth + 1) + + ",\"iterations2\":" + std::to_string(iterations2) + "}"); + // #endregion Proof proof2 = ProveTwoWeso(D, y1, iterations2, done_iterations + iterations1, weso, depth + 1, stop_signal); - + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H17", + "vdf.h:ProveTwoWeso:after_recursive_call", + "Returned from recursive ProveTwoWeso", + "{}"); + // #endregion + + int wait_polls = 0; while (!stop_signal && !prover.IsFinished()) { + if ((wait_polls % 50) == 0) { + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H52", + "vdf.h:ProveTwoWeso:wait_for_top_prover", + "Waiting for top-level prover completion", + std::string("{\"depth\":") + std::to_string(depth) + + ",\"done_iterations\":" + std::to_string(done_iterations) + + ",\"iterations_now\":" + std::to_string(weso->iterations.load()) + + ",\"wait_polls\":" + std::to_string(wait_polls) + "}"); + // #endregion + } std::this_thread::sleep_for (std::chrono::milliseconds(100)); + wait_polls++; } if (stop_signal) return Proof(); From 78092a2ee80bfc90ab93303be39227b956c0da54 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Tue, 10 Feb 2026 17:10:24 -0800 Subject: [PATCH 24/78] 2weso fail hunting 44 --- .github/workflows/test.yaml | 2 ++ src/2weso_test.cpp | 16 ++++++++++++++-- src/CMakeLists.txt | 4 +++- src/callback.h | 17 ++++++++++++++++- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 00817d26..4204acac 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -172,6 +172,8 @@ jobs: Write-Host "Instrumentation marker source line:" Select-String -Path "$env:GITHUB_WORKSPACE\src\2weso_test.cpp" -Pattern 'instrumentation_version' | ForEach-Object { $_.Line } cd build + Write-Host "2weso_test.exe PE file-header characteristics:" + & llvm-readobj --file-headers ".\\2weso_test.exe" $dllPaths = @() if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } diff --git a/src/2weso_test.cpp b/src/2weso_test.cpp index 4f0fd8aa..4698dccb 100644 --- a/src/2weso_test.cpp +++ b/src/2weso_test.cpp @@ -40,7 +40,8 @@ bool AgentDebugShouldMirror(const char* hypothesis_id) { std::strcmp(hypothesis_id, "H28") == 0 || std::strcmp(hypothesis_id, "H29") == 0 || std::strcmp(hypothesis_id, "H36") == 0 || - std::strcmp(hypothesis_id, "H37") == 0; + std::strcmp(hypothesis_id, "H37") == 0 || + std::strcmp(hypothesis_id, "H55") == 0; } void AgentDebugLog(const char* run_id, const char* hypothesis_id, const char* location, const char* message, const std::string& data_json) { @@ -127,7 +128,7 @@ int main(int argc, char const* argv[]) try "H37", "2weso_test.cpp:main:instrumentation_version_marker", "Instrumentation marker for artifact/version validation", - "{\"instrumentation_version\":\"H54\",\"source\":\"2weso_test\"}"); + "{\"instrumentation_version\":\"H55\",\"source\":\"2weso_test\"}"); // #endregion assert(is_vdf_test); //assertions should be disabled in VDF_MODE==0 @@ -209,6 +210,17 @@ int main(int argc, char const* argv[]) try "Computed L and generator", "{}"); // #endregion + // #region agent log + AgentDebugLog( + "post-fix", + "H55", + "2weso_test.cpp:main:generator_state_before_callback_ctor", + "H55 generator state before callback constructor", + std::string("{\"f_valid\":") + (f.check_valid(D) ? "true" : "false") + + ",\"f_a_bits\":" + std::to_string(f.a.num_bits()) + + ",\"f_b_bits\":" + std::to_string(f.b.num_bits()) + + ",\"f_c_bits\":" + std::to_string(f.c.num_bits()) + "}"); + // #endregion std::atomic stopped = false; fast_algorithm = false; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 658b1452..ba6b6861 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -296,7 +296,9 @@ if(BUILD_VDF_TESTS) endif() vdf_add_boost_includes(2weso_test) target_link_libraries(2weso_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) - vdf_add_windows_asm_linker_flags(2weso_test) + # Intentionally do not force /LARGEADDRESSAWARE:NO for 2weso_test. + # This target is built with CHIA_DISABLE_ASM on Windows, and we want to + # isolate crashes correlated with the linker flag. vdf_add_windows_clang_opts(2weso_test) add_executable(prover_test diff --git a/src/callback.h b/src/callback.h index d7b33a42..5f54a0e1 100644 --- a/src/callback.h +++ b/src/callback.h @@ -60,7 +60,8 @@ inline bool CallbackAgentDebugShouldMirror(const char* hypothesis_id) { std::strcmp(hypothesis_id, "H50") == 0 || std::strcmp(hypothesis_id, "H51") == 0 || std::strcmp(hypothesis_id, "H53") == 0 || - std::strcmp(hypothesis_id, "H54") == 0; + std::strcmp(hypothesis_id, "H54") == 0 || + std::strcmp(hypothesis_id, "H55") == 0; } inline void CallbackAgentDebugLog(const char* run_id, const char* hypothesis_id, const char* location, const char* message, const std::string& data_json) { @@ -246,6 +247,20 @@ class TwoWesolowskiCallback: public WesolowskiCallback { "H54 before reading source num_bits", "{}"); // #endregion + const int source_a_size = f.a.impl[0]._mp_size; + const int source_a_alloc = f.a.impl[0]._mp_alloc; + const uint64_t source_a_ptr = static_cast( + reinterpret_cast(f.a.impl[0]._mp_d)); + // #region agent log + CallbackAgentDebugLog( + "post-fix", + "H55", + "callback.h:TwoWesolowskiCallback:seed_h55_stage0_a_raw", + "H55 raw a metadata before num_bits", + std::string("{\"a_size\":") + std::to_string(source_a_size) + + ",\"a_alloc\":" + std::to_string(source_a_alloc) + + ",\"a_ptr\":" + std::to_string(source_a_ptr) + "}"); + // #endregion const uint64_t source_a_bits = static_cast(f.a.num_bits()); // #region agent log CallbackAgentDebugLog( From 5f9df6cad8f1087fc29f4d92e5b2c031ad4ee5cb Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Tue, 10 Feb 2026 17:22:21 -0800 Subject: [PATCH 25/78] 2weso fail hunting 45 --- .github/workflows/test.yaml | 44 +++++++++++++++++++++++-------------- src/CMakeLists.txt | 14 ++++++++++++ 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 4204acac..960bedba 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -123,7 +123,7 @@ jobs: "-DBUILD_HW_TOOLS=OFF" ) & cmake @cmakeArgs - cmake --build build --target vdf_client vdf_bench 1weso_test 2weso_test prover_test + cmake --build build --target vdf_client vdf_bench 1weso_test 2weso_test 2weso_test_laa_no prover_test - name: Run vdf tests (optimized) if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') @@ -178,25 +178,33 @@ jobs: if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } if ($dllPaths.Count -gt 0) { $env:PATH = ($dllPaths -join ';') + ';' + $env:PATH } - function Invoke-TestExe([string]$name, [string[]]$args = @()) { + function Invoke-TestExe([string]$name, [string[]]$args = @(), [string]$debugLog = "") { + if ($debugLog -ne "") { + $env:CHIAVDF_AGENT_DEBUG_LOG = "$env:GITHUB_WORKSPACE\\$debugLog" + if (Test-Path $env:CHIAVDF_AGENT_DEBUG_LOG) { Remove-Item $env:CHIAVDF_AGENT_DEBUG_LOG -Force } + Write-Host "CHIAVDF_AGENT_DEBUG_LOG=$env:CHIAVDF_AGENT_DEBUG_LOG" + } Write-Host "Running $name" & ".\$name.exe" @args - if ($LASTEXITCODE -ne 0) { - Write-Host "$name exit code: $LASTEXITCODE" - if ($name -eq "2weso_test" -and (Test-Path $env:CHIAVDF_AGENT_DEBUG_LOG)) { - Write-Host "=== 2weso debug log start ===" - Get-Content $env:CHIAVDF_AGENT_DEBUG_LOG - Write-Host "=== 2weso debug log end ===" - } - exit $LASTEXITCODE + $exitCode = $LASTEXITCODE + if ($debugLog -ne "" -and (Test-Path $env:CHIAVDF_AGENT_DEBUG_LOG)) { + Write-Host "=== $name debug log start ($debugLog) ===" + Get-Content $env:CHIAVDF_AGENT_DEBUG_LOG + Write-Host "=== $name debug log end ($debugLog) ===" + } + if ($exitCode -ne 0) { + Write-Host "$name exit code: $exitCode" + exit $exitCode } } - $env:CHIAVDF_AGENT_DEBUG_LOG = "$env:GITHUB_WORKSPACE\2weso-debug.ndjson" - if (Test-Path $env:CHIAVDF_AGENT_DEBUG_LOG) { Remove-Item $env:CHIAVDF_AGENT_DEBUG_LOG -Force } - Invoke-TestExe "1weso_test" + Invoke-TestExe "1weso_test" @() "1weso-debug.ndjson" Write-Host "Running 2weso_test quick precheck (100)" - Invoke-TestExe "2weso_test" @("100") - Invoke-TestExe "2weso_test" + Invoke-TestExe "2weso_test" @("100") "2weso-no-laa-quick.ndjson" + if (Test-Path ".\\2weso_test_laa_no.exe") { + Write-Host "Running 2weso_test_laa_no quick precheck (100)" + Invoke-TestExe "2weso_test_laa_no" @("100") "2weso-laa-no-quick.ndjson" + } + Invoke-TestExe "2weso_test" @() "2weso-no-laa-full.ndjson" $env:CHIAVDF_PROVER_TEST_FAST = "1" Invoke-TestExe "prover_test" @@ -205,7 +213,11 @@ jobs: uses: actions/upload-artifact@v4 with: name: 2weso-debug-windows - path: ${{ github.workspace }}/2weso-debug.ndjson + path: | + ${{ github.workspace }}/1weso-debug.ndjson + ${{ github.workspace }}/2weso-no-laa-quick.ndjson + ${{ github.workspace }}/2weso-laa-no-quick.ndjson + ${{ github.workspace }}/2weso-no-laa-full.ndjson if-no-files-found: ignore - name: Benchmark vdf_bench square (Ubuntu/Mac) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ba6b6861..966ba2e3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -300,6 +300,20 @@ if(BUILD_VDF_TESTS) # This target is built with CHIA_DISABLE_ASM on Windows, and we want to # isolate crashes correlated with the linker flag. vdf_add_windows_clang_opts(2weso_test) + if(WIN32) + # A/B isolation target: same test binary but with the Windows asm linker + # flag helper enabled (/LARGEADDRESSAWARE:NO when applicable). + add_executable(2weso_test_laa_no + ${CMAKE_CURRENT_SOURCE_DIR}/2weso_test.cpp + ) + target_sources(2weso_test_laa_no PRIVATE ${VDF_COMMON_SOURCES} ${VDF_ASM_SOURCES}) + target_compile_definitions(2weso_test_laa_no PRIVATE ${VDF_COMMON_DEFINITIONS}) + target_compile_definitions(2weso_test_laa_no PRIVATE CHIA_DISABLE_ASM) + vdf_add_boost_includes(2weso_test_laa_no) + target_link_libraries(2weso_test_laa_no PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + vdf_add_windows_asm_linker_flags(2weso_test_laa_no) + vdf_add_windows_clang_opts(2weso_test_laa_no) + endif() add_executable(prover_test ${CMAKE_CURRENT_SOURCE_DIR}/prover_test.cpp From 3a5dae4ec8a536285b36c88b4d240287db3ad58a Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Tue, 10 Feb 2026 18:04:23 -0800 Subject: [PATCH 26/78] 2weso fail hunting 46 --- .github/workflows/test.yaml | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 960bedba..b6376cef 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -174,11 +174,15 @@ jobs: cd build Write-Host "2weso_test.exe PE file-header characteristics:" & llvm-readobj --file-headers ".\\2weso_test.exe" + if (Test-Path ".\\2weso_test_laa_no.exe") { + Write-Host "2weso_test_laa_no.exe PE file-header characteristics:" + & llvm-readobj --file-headers ".\\2weso_test_laa_no.exe" + } $dllPaths = @() if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } if ($dllPaths.Count -gt 0) { $env:PATH = ($dllPaths -join ';') + ';' + $env:PATH } - function Invoke-TestExe([string]$name, [string[]]$args = @(), [string]$debugLog = "") { + function Invoke-TestExe([string]$name, [string[]]$args = @(), [string]$debugLog = "", [bool]$allowFailure = $false) { if ($debugLog -ne "") { $env:CHIAVDF_AGENT_DEBUG_LOG = "$env:GITHUB_WORKSPACE\\$debugLog" if (Test-Path $env:CHIAVDF_AGENT_DEBUG_LOG) { Remove-Item $env:CHIAVDF_AGENT_DEBUG_LOG -Force } @@ -194,19 +198,27 @@ jobs: } if ($exitCode -ne 0) { Write-Host "$name exit code: $exitCode" - exit $exitCode + if (-not $allowFailure) { + exit $exitCode + } } + return $exitCode } Invoke-TestExe "1weso_test" @() "1weso-debug.ndjson" Write-Host "Running 2weso_test quick precheck (100)" Invoke-TestExe "2weso_test" @("100") "2weso-no-laa-quick.ndjson" + Invoke-TestExe "2weso_test" @() "2weso-no-laa-full.ndjson" + $laaNoQuickExit = 0 if (Test-Path ".\\2weso_test_laa_no.exe") { Write-Host "Running 2weso_test_laa_no quick precheck (100)" - Invoke-TestExe "2weso_test_laa_no" @("100") "2weso-laa-no-quick.ndjson" + $laaNoQuickExit = Invoke-TestExe "2weso_test_laa_no" @("100") "2weso-laa-no-quick.ndjson" $true } - Invoke-TestExe "2weso_test" @() "2weso-no-laa-full.ndjson" $env:CHIAVDF_PROVER_TEST_FAST = "1" Invoke-TestExe "prover_test" + if ($laaNoQuickExit -ne 0) { + Write-Host "2weso_test_laa_no quick precheck failed with exit code: $laaNoQuickExit" + exit $laaNoQuickExit + } - name: Upload 2weso debug artifact (Windows) if: matrix.config == 'optimized=1' && startsWith(matrix.os, 'windows') && always() From 5b74a880550da4cf7008ea1984bc50782c507155 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Tue, 10 Feb 2026 19:22:24 -0800 Subject: [PATCH 27/78] cleanup: strip 2weso debug scaffolding after Windows root-cause isolation --- .github/workflows/test.yaml | 51 +------- src/2weso_test.cpp | 240 +----------------------------------- src/CMakeLists.txt | 14 --- src/callback.h | 156 +---------------------- src/prover_base.hpp | 72 +---------- 5 files changed, 9 insertions(+), 524 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index b6376cef..9ad98e95 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -123,7 +123,7 @@ jobs: "-DBUILD_HW_TOOLS=OFF" ) & cmake @cmakeArgs - cmake --build build --target vdf_client vdf_bench 1weso_test 2weso_test 2weso_test_laa_no prover_test + cmake --build build --target vdf_client vdf_bench 1weso_test 2weso_test prover_test - name: Run vdf tests (optimized) if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') @@ -169,68 +169,29 @@ jobs: run: | Write-Host "CI commit (HEAD): $env:GITHUB_SHA" git rev-parse --short HEAD - Write-Host "Instrumentation marker source line:" - Select-String -Path "$env:GITHUB_WORKSPACE\src\2weso_test.cpp" -Pattern 'instrumentation_version' | ForEach-Object { $_.Line } cd build Write-Host "2weso_test.exe PE file-header characteristics:" & llvm-readobj --file-headers ".\\2weso_test.exe" - if (Test-Path ".\\2weso_test_laa_no.exe") { - Write-Host "2weso_test_laa_no.exe PE file-header characteristics:" - & llvm-readobj --file-headers ".\\2weso_test_laa_no.exe" - } $dllPaths = @() if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } if ($dllPaths.Count -gt 0) { $env:PATH = ($dllPaths -join ';') + ';' + $env:PATH } - function Invoke-TestExe([string]$name, [string[]]$args = @(), [string]$debugLog = "", [bool]$allowFailure = $false) { - if ($debugLog -ne "") { - $env:CHIAVDF_AGENT_DEBUG_LOG = "$env:GITHUB_WORKSPACE\\$debugLog" - if (Test-Path $env:CHIAVDF_AGENT_DEBUG_LOG) { Remove-Item $env:CHIAVDF_AGENT_DEBUG_LOG -Force } - Write-Host "CHIAVDF_AGENT_DEBUG_LOG=$env:CHIAVDF_AGENT_DEBUG_LOG" - } + function Invoke-TestExe([string]$name, [string[]]$args = @()) { Write-Host "Running $name" & ".\$name.exe" @args $exitCode = $LASTEXITCODE - if ($debugLog -ne "" -and (Test-Path $env:CHIAVDF_AGENT_DEBUG_LOG)) { - Write-Host "=== $name debug log start ($debugLog) ===" - Get-Content $env:CHIAVDF_AGENT_DEBUG_LOG - Write-Host "=== $name debug log end ($debugLog) ===" - } if ($exitCode -ne 0) { Write-Host "$name exit code: $exitCode" - if (-not $allowFailure) { - exit $exitCode - } + exit $exitCode } return $exitCode } - Invoke-TestExe "1weso_test" @() "1weso-debug.ndjson" + Invoke-TestExe "1weso_test" Write-Host "Running 2weso_test quick precheck (100)" - Invoke-TestExe "2weso_test" @("100") "2weso-no-laa-quick.ndjson" - Invoke-TestExe "2weso_test" @() "2weso-no-laa-full.ndjson" - $laaNoQuickExit = 0 - if (Test-Path ".\\2weso_test_laa_no.exe") { - Write-Host "Running 2weso_test_laa_no quick precheck (100)" - $laaNoQuickExit = Invoke-TestExe "2weso_test_laa_no" @("100") "2weso-laa-no-quick.ndjson" $true - } + Invoke-TestExe "2weso_test" @("100") + Invoke-TestExe "2weso_test" $env:CHIAVDF_PROVER_TEST_FAST = "1" Invoke-TestExe "prover_test" - if ($laaNoQuickExit -ne 0) { - Write-Host "2weso_test_laa_no quick precheck failed with exit code: $laaNoQuickExit" - exit $laaNoQuickExit - } - - - name: Upload 2weso debug artifact (Windows) - if: matrix.config == 'optimized=1' && startsWith(matrix.os, 'windows') && always() - uses: actions/upload-artifact@v4 - with: - name: 2weso-debug-windows - path: | - ${{ github.workspace }}/1weso-debug.ndjson - ${{ github.workspace }}/2weso-no-laa-quick.ndjson - ${{ github.workspace }}/2weso-laa-no-quick.ndjson - ${{ github.workspace }}/2weso-no-laa-full.ndjson - if-no-files-found: ignore - name: Benchmark vdf_bench square (Ubuntu/Mac) if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') diff --git a/src/2weso_test.cpp b/src/2weso_test.cpp index 4698dccb..04dd254a 100644 --- a/src/2weso_test.cpp +++ b/src/2weso_test.cpp @@ -3,11 +3,6 @@ #include "verifier.h" #include -#include -#include -#include -#include -#include #include int segments = 7; @@ -16,100 +11,14 @@ int thread_count = 3; int gcd_base_bits=50; int gcd_128_max_iter=3; -namespace { -std::atomic g_agent_log_seq{0}; - -const char* AgentDebugLogPath() { - const char* env_path = std::getenv("CHIAVDF_AGENT_DEBUG_LOG"); - if (env_path != nullptr && env_path[0] != '\0') { - return env_path; - } - return "/Users/hoffmang/src/chiavdf/.cursor/debug.log"; -} - -bool AgentDebugShouldMirror(const char* hypothesis_id) { - const char* mirror_all = std::getenv("CHIAVDF_AGENT_DEBUG_MIRROR_ALL"); - if (mirror_all != nullptr && mirror_all[0] == '1') { - return true; - } - return std::strcmp(hypothesis_id, "H14") == 0 || - std::strcmp(hypothesis_id, "H16") == 0 || - std::strcmp(hypothesis_id, "H18") == 0 || - std::strcmp(hypothesis_id, "H19") == 0 || - std::strcmp(hypothesis_id, "H22") == 0 || - std::strcmp(hypothesis_id, "H28") == 0 || - std::strcmp(hypothesis_id, "H29") == 0 || - std::strcmp(hypothesis_id, "H36") == 0 || - std::strcmp(hypothesis_id, "H37") == 0 || - std::strcmp(hypothesis_id, "H55") == 0; -} - -void AgentDebugLog(const char* run_id, const char* hypothesis_id, const char* location, const char* message, const std::string& data_json) { - std::ofstream out(AgentDebugLogPath(), std::ios::app); - if (!out.is_open()) { - return; - } - const auto ts = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()) - .count(); - const uint64_t seq = ++g_agent_log_seq; - out << "{\"id\":\"log_" << ts << "_" << seq - << "\",\"timestamp\":" << ts - << ",\"runId\":\"" << run_id - << "\",\"hypothesisId\":\"" << hypothesis_id - << "\",\"location\":\"" << location - << "\",\"message\":\"" << message - << "\",\"data\":" << data_json - << "}\n"; - if (AgentDebugShouldMirror(hypothesis_id)) { - std::cerr << "AGENTLOG " - << "{\"id\":\"log_" << ts << "_" << seq - << "\",\"timestamp\":" << ts - << ",\"runId\":\"" << run_id - << "\",\"hypothesisId\":\"" << hypothesis_id - << "\",\"location\":\"" << location - << "\",\"message\":\"" << message - << "\",\"data\":" << data_json - << "}\n"; - } -} -} - void CheckProof(integer& D, Proof& proof, uint64_t iteration) { form x = form::generator(D); std::vector bytes; bytes.insert(bytes.end(), proof.y.begin(), proof.y.end()); bytes.insert(bytes.end(), proof.proof.begin(), proof.proof.end()); - // #region agent log - AgentDebugLog( - "pre-fix", - "H3", - "2weso_test.cpp:CheckProof:before_verify", - "CheckProof start", - std::string("{\"iteration\":") + std::to_string(iteration) + - ",\"y_size\":" + std::to_string(proof.y.size()) + - ",\"proof_size\":" + std::to_string(proof.proof.size()) + - ",\"witness_type\":" + std::to_string(proof.witness_type) + "}"); - // #endregion if (CheckProofOfTimeNWesolowski(D, DEFAULT_ELEMENT, bytes.data(), bytes.size(), iteration, 1024, proof.witness_type)) { - // #region agent log - AgentDebugLog( - "pre-fix", - "H3", - "2weso_test.cpp:CheckProof:verify_true", - "CheckProof returned true", - std::string("{\"iteration\":") + std::to_string(iteration) + "}"); - // #endregion std::cout << "Correct proof\n"; } else { - // #region agent log - AgentDebugLog( - "pre-fix", - "H3", - "2weso_test.cpp:CheckProof:verify_false", - "CheckProof returned false", - std::string("{\"iteration\":") + std::to_string(iteration) + "}"); - // #endregion std::cout << "Incorrect proof\n"; throw std::runtime_error("incorrect proof"); } @@ -122,14 +31,6 @@ int main(int argc, char const* argv[]) try // specifically with instrumented binaries that aren't as fast std::uint64_t const iter_multiplier = (argc > 1) ? std::stoull(argv[1]) : 1000000; - // #region agent log - AgentDebugLog( - "post-fix", - "H37", - "2weso_test.cpp:main:instrumentation_version_marker", - "Instrumentation marker for artifact/version validation", - "{\"instrumentation_version\":\"H55\",\"source\":\"2weso_test\"}"); - // #endregion assert(is_vdf_test); //assertions should be disabled in VDF_MODE==0 init_gmp(); @@ -140,172 +41,33 @@ int main(int argc, char const* argv[]) try gcd_base_bits=63; gcd_128_max_iter=2; } - // #region agent log - AgentDebugLog( - "pre-fix", - "H5", - "2weso_test.cpp:main:post_cpu_init", - "CPU feature and gcd parameters set", - std::string("{\"iter_multiplier\":") + std::to_string(iter_multiplier) + - ",\"has_avx2\":" + (has_avx2 ? "true" : "false") + - ",\"gcd_base_bits\":" + std::to_string(gcd_base_bits) + - ",\"gcd_128_max_iter\":" + std::to_string(gcd_128_max_iter) + "}"); - // #endregion std::vector challenge_hash({0, 0, 1, 2, 3, 3, 4, 4}); - // #region agent log - AgentDebugLog( - "pre-fix", - "H6", - "2weso_test.cpp:main:before_create_discriminant", - "About to call CreateDiscriminant", - "{\"bits\":1024,\"challenge_hash_size\":8}"); - // #endregion integer D = CreateDiscriminant(challenge_hash, 1024); - // #region agent log - AgentDebugLog( - "pre-fix", - "H6", - "2weso_test.cpp:main:after_create_discriminant", - "CreateDiscriminant returned", - std::string("{\"discriminant_sign\":") + (D < 0 ? "-1" : "1") + "}"); - // #endregion if (getenv( "warn_on_corruption_in_production" )!=nullptr) { warn_on_corruption_in_production=true; } - // #region agent log - AgentDebugLog( - "pre-fix", - "H7", - "2weso_test.cpp:main:after_warn_env", - "warn_on_corruption flag evaluated", - std::string("{\"warn_on_corruption_in_production\":") + - (warn_on_corruption_in_production ? "true" : "false") + "}"); - // #endregion set_rounding_mode(); - // #region agent log - AgentDebugLog( - "pre-fix", - "H8", - "2weso_test.cpp:main:after_set_rounding_mode", - "set_rounding_mode completed", - "{}"); - // #endregion - // #region agent log - AgentDebugLog( - "pre-fix", - "H9", - "2weso_test.cpp:main:before_root_generator", - "About to compute L and generator", - "{}"); - // #endregion integer L=root(-D, 4); form f=form::generator(D); - // #region agent log - AgentDebugLog( - "pre-fix", - "H9", - "2weso_test.cpp:main:after_root_generator", - "Computed L and generator", - "{}"); - // #endregion - // #region agent log - AgentDebugLog( - "post-fix", - "H55", - "2weso_test.cpp:main:generator_state_before_callback_ctor", - "H55 generator state before callback constructor", - std::string("{\"f_valid\":") + (f.check_valid(D) ? "true" : "false") + - ",\"f_a_bits\":" + std::to_string(f.a.num_bits()) + - ",\"f_b_bits\":" + std::to_string(f.b.num_bits()) + - ",\"f_c_bits\":" + std::to_string(f.c.num_bits()) + "}"); - // #endregion - std::atomic stopped = false; fast_algorithm = false; two_weso = true; - // #region agent log - AgentDebugLog( - "pre-fix", - "H10", - "2weso_test.cpp:main:before_callback_ctor", - "About to construct TwoWesolowskiCallback", - "{}"); - // #endregion const uint64_t max_test_iteration = 100 * iter_multiplier; + (void)max_test_iteration; TwoWesolowskiCallback weso(D, f); - // #region agent log - AgentDebugLog( - "pre-fix", - "H10", - "2weso_test.cpp:main:after_callback_ctor", - "Constructed TwoWesolowskiCallback", - "{}"); - // #endregion FastStorage* fast_storage = NULL; - // #region agent log - AgentDebugLog( - "pre-fix", - "H1", - "2weso_test.cpp:main:before_worker_start", - "Starting repeated_square worker thread", - std::string("{\"fast_algorithm\":") + (fast_algorithm ? "true" : "false") + - ",\"two_weso\":" + (two_weso ? "true" : "false") + "}"); - // #endregion std::thread vdf_worker(repeated_square, 0, f, D, L, &weso, fast_storage, std::ref(stopped)); - // #region agent log - AgentDebugLog( - "pre-fix", - "H1", - "2weso_test.cpp:main:after_worker_start", - "Worker thread started", - std::string("{\"worker_joinable\":") + (vdf_worker.joinable() ? "true" : "false") + "}"); - // #endregion auto stop_worker = [&]() { - // #region agent log - AgentDebugLog( - "pre-fix", - "H4", - "2weso_test.cpp:main:stop_worker_enter", - "stop_worker invoked", - std::string("{\"worker_joinable_before\":") + (vdf_worker.joinable() ? "true" : "false") + "}"); - // #endregion stopped = true; if (vdf_worker.joinable()) { vdf_worker.join(); } - // #region agent log - AgentDebugLog( - "pre-fix", - "H4", - "2weso_test.cpp:main:stop_worker_exit", - "stop_worker completed", - std::string("{\"worker_joinable_after\":") + (vdf_worker.joinable() ? "true" : "false") + "}"); - // #endregion }; try { auto run_test = [&](uint64_t iteration) { - // #region agent log - AgentDebugLog( - "pre-fix", - "H2", - "2weso_test.cpp:main:before_prove", - "Calling ProveTwoWeso", - std::string("{\"iteration\":") + std::to_string(iteration) + "}"); - // #endregion Proof proof = ProveTwoWeso(D, f, iteration, 0, &weso, 0, stopped); - // #region agent log - AgentDebugLog( - "pre-fix", - "H2", - "2weso_test.cpp:main:after_prove", - "ProveTwoWeso returned", - std::string("{\"iteration\":") + std::to_string(iteration) + - ",\"y_size\":" + std::to_string(proof.y.size()) + - ",\"proof_size\":" + std::to_string(proof.proof.size()) + - ",\"witness_type\":" + std::to_string(proof.witness_type) + "}"); - // #endregion CheckProof(D, proof, iteration); }; // Test 1 - 1 million iters. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 966ba2e3..ba6b6861 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -300,20 +300,6 @@ if(BUILD_VDF_TESTS) # This target is built with CHIA_DISABLE_ASM on Windows, and we want to # isolate crashes correlated with the linker flag. vdf_add_windows_clang_opts(2weso_test) - if(WIN32) - # A/B isolation target: same test binary but with the Windows asm linker - # flag helper enabled (/LARGEADDRESSAWARE:NO when applicable). - add_executable(2weso_test_laa_no - ${CMAKE_CURRENT_SOURCE_DIR}/2weso_test.cpp - ) - target_sources(2weso_test_laa_no PRIVATE ${VDF_COMMON_SOURCES} ${VDF_ASM_SOURCES}) - target_compile_definitions(2weso_test_laa_no PRIVATE ${VDF_COMMON_DEFINITIONS}) - target_compile_definitions(2weso_test_laa_no PRIVATE CHIA_DISABLE_ASM) - vdf_add_boost_includes(2weso_test_laa_no) - target_link_libraries(2weso_test_laa_no PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) - vdf_add_windows_asm_linker_flags(2weso_test_laa_no) - vdf_add_windows_clang_opts(2weso_test_laa_no) - endif() add_executable(prover_test ${CMAKE_CURRENT_SOURCE_DIR}/prover_test.cpp diff --git a/src/callback.h b/src/callback.h index 5f54a0e1..abea9277 100644 --- a/src/callback.h +++ b/src/callback.h @@ -4,11 +4,6 @@ #include "util.h" #include "nudupl_listener.h" #include -#include -#include -#include -#include -#include #include #include #include @@ -20,80 +15,7 @@ const int kWindowSize = 20; const int kMaxItersAllowed = 8e8; const int kSwitchIters = 91000000; -inline const char* CallbackAgentDebugLogPath() { - const char* env_path = std::getenv("CHIAVDF_AGENT_DEBUG_LOG"); - if (env_path != nullptr && env_path[0] != '\0') { - return env_path; - } - return "/Users/hoffmang/src/chiavdf/.cursor/debug.log"; -} - -inline bool CallbackAgentDebugShouldMirror(const char* hypothesis_id) { - const char* mirror_all = std::getenv("CHIAVDF_AGENT_DEBUG_MIRROR_ALL"); - if (mirror_all != nullptr && mirror_all[0] == '1') { - return true; - } - return std::strcmp(hypothesis_id, "H14") == 0 || - std::strcmp(hypothesis_id, "H16") == 0 || - std::strcmp(hypothesis_id, "H18") == 0 || - std::strcmp(hypothesis_id, "H19") == 0 || - std::strcmp(hypothesis_id, "H22") == 0 || - std::strcmp(hypothesis_id, "H28") == 0 || - std::strcmp(hypothesis_id, "H29") == 0 || - std::strcmp(hypothesis_id, "H32") == 0 || - std::strcmp(hypothesis_id, "H33") == 0 || - std::strcmp(hypothesis_id, "H34") == 0 || - std::strcmp(hypothesis_id, "H35") == 0 || - std::strcmp(hypothesis_id, "H36") == 0 || - std::strcmp(hypothesis_id, "H38") == 0 || - std::strcmp(hypothesis_id, "H39") == 0 || - std::strcmp(hypothesis_id, "H40") == 0 || - std::strcmp(hypothesis_id, "H41") == 0 || - std::strcmp(hypothesis_id, "H42") == 0 || - std::strcmp(hypothesis_id, "H43") == 0 || - std::strcmp(hypothesis_id, "H44") == 0 || - std::strcmp(hypothesis_id, "H45") == 0 || - std::strcmp(hypothesis_id, "H46") == 0 || - std::strcmp(hypothesis_id, "H47") == 0 || - std::strcmp(hypothesis_id, "H48") == 0 || - std::strcmp(hypothesis_id, "H49") == 0 || - std::strcmp(hypothesis_id, "H50") == 0 || - std::strcmp(hypothesis_id, "H51") == 0 || - std::strcmp(hypothesis_id, "H53") == 0 || - std::strcmp(hypothesis_id, "H54") == 0 || - std::strcmp(hypothesis_id, "H55") == 0; -} - -inline void CallbackAgentDebugLog(const char* run_id, const char* hypothesis_id, const char* location, const char* message, const std::string& data_json) { - static std::atomic seq{0}; - std::ofstream out(CallbackAgentDebugLogPath(), std::ios::app); - if (!out.is_open()) { - return; - } - const auto ts = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()) - .count(); - const uint64_t id = ++seq; - out << "{\"id\":\"log_" << ts << "_" << id - << "\",\"timestamp\":" << ts - << ",\"runId\":\"" << run_id - << "\",\"hypothesisId\":\"" << hypothesis_id - << "\",\"location\":\"" << location - << "\",\"message\":\"" << message - << "\",\"data\":" << data_json - << "}\n"; - if (CallbackAgentDebugShouldMirror(hypothesis_id)) { - std::cerr << "AGENTLOG " - << "{\"id\":\"log_" << ts << "_" << id - << "\",\"timestamp\":" << ts - << ",\"runId\":\"" << run_id - << "\",\"hypothesisId\":\"" << hypothesis_id - << "\",\"location\":\"" << location - << "\",\"message\":\"" << message - << "\",\"data\":" << data_json - << "}\n"; - } -} +#define CallbackAgentDebugLog(...) do {} while (0) class WesolowskiCallback :public INUDUPLListener { public: @@ -239,84 +161,8 @@ class TwoWesolowskiCallback: public WesolowskiCallback { // #region agent log CallbackAgentDebugLog("pre-fix", "H13", "callback.h:TwoWesolowskiCallback:before_seed_form_assign", "Assigning initial form to forms[0]", "{}"); // #endregion - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H54", - "callback.h:TwoWesolowskiCallback:seed_h54_stage0_pre_source_reads", - "H54 before reading source num_bits", - "{}"); - // #endregion - const int source_a_size = f.a.impl[0]._mp_size; - const int source_a_alloc = f.a.impl[0]._mp_alloc; - const uint64_t source_a_ptr = static_cast( - reinterpret_cast(f.a.impl[0]._mp_d)); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H55", - "callback.h:TwoWesolowskiCallback:seed_h55_stage0_a_raw", - "H55 raw a metadata before num_bits", - std::string("{\"a_size\":") + std::to_string(source_a_size) + - ",\"a_alloc\":" + std::to_string(source_a_alloc) + - ",\"a_ptr\":" + std::to_string(source_a_ptr) + "}"); - // #endregion - const uint64_t source_a_bits = static_cast(f.a.num_bits()); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H54", - "callback.h:TwoWesolowskiCallback:seed_h54_stage1_after_a_bits", - "H54 after reading source a bits", - std::string("{\"source_a_bits\":") + std::to_string(source_a_bits) + "}"); - // #endregion - const uint64_t source_b_bits = static_cast(f.b.num_bits()); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H54", - "callback.h:TwoWesolowskiCallback:seed_h54_stage2_after_b_bits", - "H54 after reading source b bits", - std::string("{\"source_b_bits\":") + std::to_string(source_b_bits) + "}"); - // #endregion - const uint64_t source_c_bits = static_cast(f.c.num_bits()); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H54", - "callback.h:TwoWesolowskiCallback:seed_h54_stage3_after_c_bits", - "H54 after reading source c bits", - std::string("{\"source_c_bits\":") + std::to_string(source_c_bits) + "}"); - // #endregion - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H53", - "callback.h:TwoWesolowskiCallback:seed_stage0_source_state", - "H53 source form state before seed assignment", - std::string("{\"source_a_bits\":") + std::to_string(source_a_bits) + - ",\"source_b_bits\":" + std::to_string(source_b_bits) + - ",\"source_c_bits\":" + std::to_string(source_c_bits) + "}"); - // #endregion - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H53", - "callback.h:TwoWesolowskiCallback:seed_stage1_dest_slot", - "H53 destination slot prepared for seed assignment", - std::string("{\"forms_capacity\":") + std::to_string(forms_capacity) + "}"); - // #endregion forms[0] = f; // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H53", - "callback.h:TwoWesolowskiCallback:seed_stage2_after_assign", - "H53 seed assignment completed", - std::string("{\"stored_valid\":") + (forms[0].check_valid(D) ? "true" : "false") + - ",\"stored_a_bits\":" + std::to_string(forms[0].a.num_bits()) + "}"); - // #endregion - // #region agent log CallbackAgentDebugLog("pre-fix", "H13", "callback.h:TwoWesolowskiCallback:after_seed_form_assign", "Assigned initial form to forms[0]", "{}"); // #endregion kl = 10; diff --git a/src/prover_base.hpp b/src/prover_base.hpp index 7dbfe881..f6c40e56 100644 --- a/src/prover_base.hpp +++ b/src/prover_base.hpp @@ -1,82 +1,12 @@ #ifndef PROVER_BASE_H #define PROVER_BASE_H -#include -#include -#include -#include -#include #include #include "proof_common.h" #include "util.h" -inline const char* ProverAgentDebugLogPath() { - const char* env_path = std::getenv("CHIAVDF_AGENT_DEBUG_LOG"); - if (env_path != nullptr && env_path[0] != '\0') { - return env_path; - } - return "/Users/hoffmang/src/chiavdf/.cursor/debug.log"; -} - -inline bool ProverAgentDebugShouldMirror(const char* hypothesis_id) { - const char* mirror_all = std::getenv("CHIAVDF_AGENT_DEBUG_MIRROR_ALL"); - if (mirror_all != nullptr && mirror_all[0] == '1') { - return true; - } - return std::strcmp(hypothesis_id, "H14") == 0 || - std::strcmp(hypothesis_id, "H16") == 0 || - std::strcmp(hypothesis_id, "H18") == 0 || - std::strcmp(hypothesis_id, "H19") == 0 || - std::strcmp(hypothesis_id, "H22") == 0 || - std::strcmp(hypothesis_id, "H28") == 0 || - std::strcmp(hypothesis_id, "H29") == 0 || - std::strcmp(hypothesis_id, "H32") == 0 || - std::strcmp(hypothesis_id, "H33") == 0 || - std::strcmp(hypothesis_id, "H34") == 0 || - std::strcmp(hypothesis_id, "H35") == 0 || - std::strcmp(hypothesis_id, "H36") == 0 || - std::strcmp(hypothesis_id, "H38") == 0 || - std::strcmp(hypothesis_id, "H40") == 0 || - std::strcmp(hypothesis_id, "H41") == 0 || - std::strcmp(hypothesis_id, "H42") == 0 || - std::strcmp(hypothesis_id, "H43") == 0 || - std::strcmp(hypothesis_id, "H44") == 0 || - std::strcmp(hypothesis_id, "H45") == 0 || - std::strcmp(hypothesis_id, "H46") == 0 || - std::strcmp(hypothesis_id, "H52") == 0; -} - -inline void ProverAgentDebugLog(const char* run_id, const char* hypothesis_id, const char* location, const char* message, const std::string& data_json) { - static std::atomic seq{0}; - std::ofstream out(ProverAgentDebugLogPath(), std::ios::app); - if (!out.is_open()) { - return; - } - const auto ts = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()) - .count(); - const uint64_t id = ++seq; - out << "{\"id\":\"log_" << ts << "_" << id - << "\",\"timestamp\":" << ts - << ",\"runId\":\"" << run_id - << "\",\"hypothesisId\":\"" << hypothesis_id - << "\",\"location\":\"" << location - << "\",\"message\":\"" << message - << "\",\"data\":" << data_json - << "}\n"; - if (ProverAgentDebugShouldMirror(hypothesis_id)) { - std::cerr << "AGENTLOG " - << "{\"id\":\"log_" << ts << "_" << id - << "\",\"timestamp\":" << ts - << ",\"runId\":\"" << run_id - << "\",\"hypothesisId\":\"" << hypothesis_id - << "\",\"location\":\"" << location - << "\",\"message\":\"" << message - << "\",\"data\":" << data_json - << "}\n"; - } -} +#define ProverAgentDebugLog(...) do {} while (0) class Prover { public: From b364b60b12e8bb37e41637816d34c784eab50a97 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Tue, 10 Feb 2026 20:19:33 -0800 Subject: [PATCH 28/78] ci - add an asm path to the c++ test path, fix HW headers --- .github/workflows/test.yaml | 16 +++++++++++++++- src/CMakeLists.txt | 35 +++++++++++++++++++++++++++++++++++ src/callback.h | 1 + src/prover_base.hpp | 1 + 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 9ad98e95..84408420 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -123,7 +123,7 @@ jobs: "-DBUILD_HW_TOOLS=OFF" ) & cmake @cmakeArgs - cmake --build build --target vdf_client vdf_bench 1weso_test 2weso_test prover_test + cmake --build build --target vdf_client vdf_bench 1weso_test 2weso_test prover_test 1weso_test_asm 2weso_test_asm prover_test_asm - name: Run vdf tests (optimized) if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') @@ -172,6 +172,10 @@ jobs: cd build Write-Host "2weso_test.exe PE file-header characteristics:" & llvm-readobj --file-headers ".\\2weso_test.exe" + if (Test-Path ".\\2weso_test_asm.exe") { + Write-Host "2weso_test_asm.exe PE file-header characteristics:" + & llvm-readobj --file-headers ".\\2weso_test_asm.exe" + } $dllPaths = @() if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } @@ -192,6 +196,16 @@ jobs: Invoke-TestExe "2weso_test" $env:CHIAVDF_PROVER_TEST_FAST = "1" Invoke-TestExe "prover_test" + if (Test-Path ".\\1weso_test_asm.exe") { + Write-Host "Running asm parity flow" + Invoke-TestExe "1weso_test_asm" + Write-Host "Running 2weso_test_asm quick precheck (100)" + Invoke-TestExe "2weso_test_asm" @("100") + Write-Host "Running 2weso_test_asm with half max iterations (500000)" + Invoke-TestExe "2weso_test_asm" @("500000") + $env:CHIAVDF_PROVER_TEST_FAST = "1" + Invoke-TestExe "prover_test_asm" + } - name: Benchmark vdf_bench square (Ubuntu/Mac) if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ba6b6861..a1164ba4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -313,6 +313,41 @@ if(BUILD_VDF_TESTS) target_link_libraries(prover_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) vdf_add_windows_asm_linker_flags(prover_test) vdf_add_windows_clang_opts(prover_test) + + # On Windows, keep the default test binaries on CHIA_DISABLE_ASM for stable + # algorithm-level coverage, and add explicit asm-enabled counterparts for + # production-parity coverage under /LARGEADDRESSAWARE:NO. + if(WIN32 AND ENABLE_GNU_ASM) + add_executable(1weso_test_asm + ${CMAKE_CURRENT_SOURCE_DIR}/1weso_test.cpp + ) + target_sources(1weso_test_asm PRIVATE ${VDF_COMMON_SOURCES} ${VDF_ASM_SOURCES}) + target_compile_definitions(1weso_test_asm PRIVATE ${VDF_COMMON_DEFINITIONS}) + vdf_add_boost_includes(1weso_test_asm) + target_link_libraries(1weso_test_asm PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + vdf_add_windows_asm_linker_flags(1weso_test_asm) + vdf_add_windows_clang_opts(1weso_test_asm) + + add_executable(2weso_test_asm + ${CMAKE_CURRENT_SOURCE_DIR}/2weso_test.cpp + ) + target_sources(2weso_test_asm PRIVATE ${VDF_COMMON_SOURCES} ${VDF_ASM_SOURCES}) + target_compile_definitions(2weso_test_asm PRIVATE ${VDF_COMMON_DEFINITIONS}) + vdf_add_boost_includes(2weso_test_asm) + target_link_libraries(2weso_test_asm PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + vdf_add_windows_asm_linker_flags(2weso_test_asm) + vdf_add_windows_clang_opts(2weso_test_asm) + + add_executable(prover_test_asm + ${CMAKE_CURRENT_SOURCE_DIR}/prover_test.cpp + ) + target_sources(prover_test_asm PRIVATE ${VDF_COMMON_SOURCES} ${VDF_ASM_SOURCES}) + target_compile_definitions(prover_test_asm PRIVATE ${VDF_COMMON_DEFINITIONS}) + vdf_add_boost_includes(prover_test_asm) + target_link_libraries(prover_test_asm PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + vdf_add_windows_asm_linker_flags(prover_test_asm) + vdf_add_windows_clang_opts(prover_test_asm) + endif() endif() if(BUILD_HW_TOOLS) diff --git a/src/callback.h b/src/callback.h index abea9277..57d770a0 100644 --- a/src/callback.h +++ b/src/callback.h @@ -4,6 +4,7 @@ #include "util.h" #include "nudupl_listener.h" #include +#include #include #include #include diff --git a/src/prover_base.hpp b/src/prover_base.hpp index f6c40e56..54e27056 100644 --- a/src/prover_base.hpp +++ b/src/prover_base.hpp @@ -1,6 +1,7 @@ #ifndef PROVER_BASE_H #define PROVER_BASE_H +#include #include #include "proof_common.h" From 651ee886be30a6d762451aeafd6fe718e8de4234 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Tue, 10 Feb 2026 21:22:20 -0800 Subject: [PATCH 29/78] ci - bring windows back around to main ubuntu/macos testing --- .github/workflows/test.yaml | 28 +- src/CMakeLists.txt | 34 - src/callback.h | 579 ----------------- src/prover_base.hpp | 1213 ----------------------------------- src/provers.h | 505 --------------- src/vdf.h | 231 +------ 6 files changed, 6 insertions(+), 2584 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 84408420..d6005c70 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -123,7 +123,7 @@ jobs: "-DBUILD_HW_TOOLS=OFF" ) & cmake @cmakeArgs - cmake --build build --target vdf_client vdf_bench 1weso_test 2weso_test prover_test 1weso_test_asm 2weso_test_asm prover_test_asm + cmake --build build --target vdf_client vdf_bench 1weso_test 2weso_test prover_test - name: Run vdf tests (optimized) if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') @@ -170,12 +170,6 @@ jobs: Write-Host "CI commit (HEAD): $env:GITHUB_SHA" git rev-parse --short HEAD cd build - Write-Host "2weso_test.exe PE file-header characteristics:" - & llvm-readobj --file-headers ".\\2weso_test.exe" - if (Test-Path ".\\2weso_test_asm.exe") { - Write-Host "2weso_test_asm.exe PE file-header characteristics:" - & llvm-readobj --file-headers ".\\2weso_test_asm.exe" - } $dllPaths = @() if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } @@ -190,22 +184,10 @@ jobs: } return $exitCode } - Invoke-TestExe "1weso_test" - Write-Host "Running 2weso_test quick precheck (100)" - Invoke-TestExe "2weso_test" @("100") - Invoke-TestExe "2weso_test" - $env:CHIAVDF_PROVER_TEST_FAST = "1" - Invoke-TestExe "prover_test" - if (Test-Path ".\\1weso_test_asm.exe") { - Write-Host "Running asm parity flow" - Invoke-TestExe "1weso_test_asm" - Write-Host "Running 2weso_test_asm quick precheck (100)" - Invoke-TestExe "2weso_test_asm" @("100") - Write-Host "Running 2weso_test_asm with half max iterations (500000)" - Invoke-TestExe "2weso_test_asm" @("500000") - $env:CHIAVDF_PROVER_TEST_FAST = "1" - Invoke-TestExe "prover_test_asm" - } + Write-Host "Running 1weso_test" + Invoke-TestExe "1weso_test" @("1000") + Write-Host "Running 2weso_test" + Invoke-TestExe "2weso_test" @("1000") - name: Benchmark vdf_bench square (Ubuntu/Mac) if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a1164ba4..982b620e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -314,40 +314,6 @@ if(BUILD_VDF_TESTS) vdf_add_windows_asm_linker_flags(prover_test) vdf_add_windows_clang_opts(prover_test) - # On Windows, keep the default test binaries on CHIA_DISABLE_ASM for stable - # algorithm-level coverage, and add explicit asm-enabled counterparts for - # production-parity coverage under /LARGEADDRESSAWARE:NO. - if(WIN32 AND ENABLE_GNU_ASM) - add_executable(1weso_test_asm - ${CMAKE_CURRENT_SOURCE_DIR}/1weso_test.cpp - ) - target_sources(1weso_test_asm PRIVATE ${VDF_COMMON_SOURCES} ${VDF_ASM_SOURCES}) - target_compile_definitions(1weso_test_asm PRIVATE ${VDF_COMMON_DEFINITIONS}) - vdf_add_boost_includes(1weso_test_asm) - target_link_libraries(1weso_test_asm PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) - vdf_add_windows_asm_linker_flags(1weso_test_asm) - vdf_add_windows_clang_opts(1weso_test_asm) - - add_executable(2weso_test_asm - ${CMAKE_CURRENT_SOURCE_DIR}/2weso_test.cpp - ) - target_sources(2weso_test_asm PRIVATE ${VDF_COMMON_SOURCES} ${VDF_ASM_SOURCES}) - target_compile_definitions(2weso_test_asm PRIVATE ${VDF_COMMON_DEFINITIONS}) - vdf_add_boost_includes(2weso_test_asm) - target_link_libraries(2weso_test_asm PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) - vdf_add_windows_asm_linker_flags(2weso_test_asm) - vdf_add_windows_clang_opts(2weso_test_asm) - - add_executable(prover_test_asm - ${CMAKE_CURRENT_SOURCE_DIR}/prover_test.cpp - ) - target_sources(prover_test_asm PRIVATE ${VDF_COMMON_SOURCES} ${VDF_ASM_SOURCES}) - target_compile_definitions(prover_test_asm PRIVATE ${VDF_COMMON_DEFINITIONS}) - vdf_add_boost_includes(prover_test_asm) - target_link_libraries(prover_test_asm PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) - vdf_add_windows_asm_linker_flags(prover_test_asm) - vdf_add_windows_clang_opts(prover_test_asm) - endif() endif() if(BUILD_HW_TOOLS) diff --git a/src/callback.h b/src/callback.h index 57d770a0..2c21a80c 100644 --- a/src/callback.h +++ b/src/callback.h @@ -16,27 +16,13 @@ const int kWindowSize = 20; const int kMaxItersAllowed = 8e8; const int kSwitchIters = 91000000; -#define CallbackAgentDebugLog(...) do {} while (0) - class WesolowskiCallback :public INUDUPLListener { public: WesolowskiCallback(integer& D) { - // #region agent log - CallbackAgentDebugLog("pre-fix", "H11", "callback.h:WesolowskiCallback:ctor_enter", "Entering WesolowskiCallback constructor", "{}"); - // #endregion vdfo = new vdf_original(); - // #region agent log - CallbackAgentDebugLog("pre-fix", "H11", "callback.h:WesolowskiCallback:after_vdfo_new", "Allocated vdf_original", "{}"); - // #endregion reducer = new PulmarkReducer(); - // #region agent log - CallbackAgentDebugLog("pre-fix", "H11", "callback.h:WesolowskiCallback:after_reducer_new", "Allocated PulmarkReducer", "{}"); - // #endregion this->D = D; this->L = root(-D, 4); - // #region agent log - CallbackAgentDebugLog("pre-fix", "H11", "callback.h:WesolowskiCallback:ctor_exit", "Leaving WesolowskiCallback constructor", "{}"); - // #endregion } virtual ~WesolowskiCallback() { @@ -138,39 +124,15 @@ class OneWesolowskiCallback: public WesolowskiCallback { class TwoWesolowskiCallback: public WesolowskiCallback { public: TwoWesolowskiCallback(integer& D, const form& f) : WesolowskiCallback(D) { - // #region agent log - CallbackAgentDebugLog("pre-fix", "H12", "callback.h:TwoWesolowskiCallback:ctor_enter", "Entering TwoWesolowskiCallback constructor", "{}"); - // #endregion const uint64_t early_points = static_cast(kSwitchIters) / 10; const uint64_t late_points = (static_cast(kMaxItersAllowed) - static_cast(kSwitchIters)) / 100; const size_t space_needed = static_cast(early_points + late_points); forms_capacity = space_needed; - // #region agent log - CallbackAgentDebugLog( - "pre-fix", - "H12", - "callback.h:TwoWesolowskiCallback:before_forms_alloc", - "Allocating forms array", - std::string("{\"space_needed\":") + std::to_string(space_needed) + - ",\"max_iters_fixed\":" + std::to_string(kMaxItersAllowed) + "}"); - // #endregion forms.reset(new form[space_needed]); - // #region agent log - CallbackAgentDebugLog("pre-fix", "H12", "callback.h:TwoWesolowskiCallback:after_forms_alloc", "Allocated forms array", "{}"); - // #endregion - // #region agent log - CallbackAgentDebugLog("pre-fix", "H13", "callback.h:TwoWesolowskiCallback:before_seed_form_assign", "Assigning initial form to forms[0]", "{}"); - // #endregion forms[0] = f; - // #region agent log - CallbackAgentDebugLog("pre-fix", "H13", "callback.h:TwoWesolowskiCallback:after_seed_form_assign", "Assigned initial form to forms[0]", "{}"); - // #endregion kl = 10; switch_iters = -1; - // #region agent log - CallbackAgentDebugLog("pre-fix", "H12", "callback.h:TwoWesolowskiCallback:ctor_exit", "Leaving TwoWesolowskiCallback constructor", "{}"); - // #endregion } void IncreaseConstants(uint64_t num_iters) { @@ -188,500 +150,11 @@ class TwoWesolowskiCallback: public WesolowskiCallback { } form GetFormCopy(uint64_t power) { - if (power >= 12500590 && power <= 12500610) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H47", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h47_stage0_pre_lock", - "H47 stage0 pre-lock", - std::string("{\"power\":") + std::to_string(power) + "}"); - // #endregion - } - if (power >= 12602260 && power <= 12602280) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H48", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h48_stage0_pre_lock", - "H48 stage0 pre-lock", - std::string("{\"power\":") + std::to_string(power) + "}"); - // #endregion - } - if (power >= 12500360 && power <= 12500390) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H49", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h49_stage0_pre_lock", - "H49 stage0 pre-lock", - std::string("{\"power\":") + std::to_string(power) + "}"); - // #endregion - } - if (power >= 12500920 && power <= 12500960) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H50", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h50_stage0_pre_lock", - "H50 stage0 pre-lock", - std::string("{\"power\":") + std::to_string(power) + "}"); - // #endregion - } - if (power >= 12500610 && power <= 12500630) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H51", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h51_stage0_pre_lock", - "H51 stage0 pre-lock", - std::string("{\"power\":") + std::to_string(power) + "}"); - // #endregion - } std::lock_guard lk(forms_mutex); - if (power >= 12500590 && power <= 12500610) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H47", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h47_stage1_post_lock", - "H47 stage1 post-lock", - std::string("{\"power\":") + std::to_string(power) + "}"); - // #endregion - } - if (power >= 12602260 && power <= 12602280) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H48", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h48_stage1_post_lock", - "H48 stage1 post-lock", - std::string("{\"power\":") + std::to_string(power) + "}"); - // #endregion - } - if (power >= 12500360 && power <= 12500390) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H49", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h49_stage1_post_lock", - "H49 stage1 post-lock", - std::string("{\"power\":") + std::to_string(power) + "}"); - // #endregion - } - if (power >= 12500920 && power <= 12500960) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H50", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h50_stage1_post_lock", - "H50 stage1 post-lock", - std::string("{\"power\":") + std::to_string(power) + "}"); - // #endregion - } - if (power >= 12500610 && power <= 12500630) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H51", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h51_stage1_post_lock", - "H51 stage1 post-lock", - std::string("{\"power\":") + std::to_string(power) + "}"); - // #endregion - } const int pos = GetPosition(power); - if (power >= 12500590 && power <= 12500610) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H47", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h47_stage2_after_getposition", - "H47 stage2 after GetPosition", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"forms_capacity\":" + std::to_string(forms_capacity) + "}"); - // #endregion - } - if (power >= 12602260 && power <= 12602280) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H48", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h48_stage2_after_getposition", - "H48 stage2 after GetPosition", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"forms_capacity\":" + std::to_string(forms_capacity) + "}"); - // #endregion - } - if (power >= 12500360 && power <= 12500390) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H49", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h49_stage2_after_getposition", - "H49 stage2 after GetPosition", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"forms_capacity\":" + std::to_string(forms_capacity) + "}"); - // #endregion - } - if (power >= 12500920 && power <= 12500960) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H50", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h50_stage2_after_getposition", - "H50 stage2 after GetPosition", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"forms_capacity\":" + std::to_string(forms_capacity) + "}"); - // #endregion - } - if (power >= 12500610 && power <= 12500630) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H51", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h51_stage2_after_getposition", - "H51 stage2 after GetPosition", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"forms_capacity\":" + std::to_string(forms_capacity) + "}"); - // #endregion - } if (pos < 0 || static_cast(pos) >= forms_capacity) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H16", - "callback.h:TwoWesolowskiCallback:GetFormCopy_oob", - "GetFormCopy out of bounds", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"forms_capacity\":" + std::to_string(forms_capacity) + - ",\"switch_iters\":" + std::to_string(switch_iters) + - ",\"switch_index\":" + std::to_string(switch_index) + "}"); - // #endregion throw std::runtime_error("TwoWesolowskiCallback::GetFormCopy out of bounds"); } - if (power >= 12500590 && power <= 12500610) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H47", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h47_stage3_before_return_copy", - "H47 stage3 before return copy", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + "}"); - // #endregion - } - if (power >= 12500360 && power <= 12500390) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H49", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h49_stage3_before_source_deref", - "H49 stage3 before source dereference", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + "}"); - // #endregion - } - if (power >= 12500920 && power <= 12500960) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H50", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h50_stage3_before_source_deref", - "H50 stage3 before source dereference", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + "}"); - // #endregion - } - if (power >= 12500610 && power <= 12500630) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H51", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h51_stage3_before_source_deref", - "H51 stage3 before source dereference", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + "}"); - // #endregion - } - if (power >= 12650010 && power <= 12652000) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H32", - "callback.h:TwoWesolowskiCallback:GetFormCopy_micro_source_state", - "Micro window source form state before copy", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"source_valid\":" + (forms[static_cast(pos)].check_valid(D) ? "true" : "false") + - ",\"source_a_bits\":" + std::to_string(forms[static_cast(pos)].a.num_bits()) + "}"); - // #endregion - } - if (power >= 12644200 && power <= 12644450) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H34", - "callback.h:TwoWesolowskiCallback:GetFormCopy_focused_source_state", - "Focused window source form state before copy", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"source_valid\":" + (forms[static_cast(pos)].check_valid(D) ? "true" : "false") + - ",\"source_a_bits\":" + std::to_string(forms[static_cast(pos)].a.num_bits()) + "}"); - // #endregion - } - if (power >= 12647010 && power <= 12647600 && - !(power >= 12647080 && power <= 12647220)) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H35", - "callback.h:TwoWesolowskiCallback:GetFormCopy_post700_source_state", - "Post-264700 focused source form state before copy", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"source_valid\":" + (forms[static_cast(pos)].check_valid(D) ? "true" : "false") + - ",\"source_a_bits\":" + std::to_string(forms[static_cast(pos)].a.num_bits()) + "}"); - // #endregion - } - if (power >= 12647080 && power <= 12647220) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H39", - "callback.h:TwoWesolowskiCallback:GetFormCopy_stage0_before_source_deref", - "H39 stage0 before source dereference", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + "}"); - // #endregion - form& source = forms[static_cast(pos)]; - const bool source_valid = source.check_valid(D); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H39", - "callback.h:TwoWesolowskiCallback:GetFormCopy_stage1_after_check_valid", - "H39 stage1 after check_valid", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"source_valid\":" + (source_valid ? "true" : "false") + "}"); - // #endregion - const uint64_t source_a_bits = static_cast(source.a.num_bits()); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H39", - "callback.h:TwoWesolowskiCallback:GetFormCopy_stage2_after_num_bits", - "H39 stage2 after source num_bits", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"source_a_bits\":" + std::to_string(source_a_bits) + "}"); - // #endregion - } - if (power >= 12699800 && power <= 12700600) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H36", - "callback.h:TwoWesolowskiCallback:GetFormCopy_270k_source_state", - "270k window source form state before copy", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"source_valid\":" + (forms[static_cast(pos)].check_valid(D) ? "true" : "false") + - ",\"source_a_bits\":" + std::to_string(forms[static_cast(pos)].a.num_bits()) + "}"); - // #endregion - } - if (power >= 12643180 && power <= 12643240) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H38", - "callback.h:TwoWesolowskiCallback:GetFormCopy_crash_window_source_state", - "Crash-window source form state before copy", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"source_valid\":" + (forms[static_cast(pos)].check_valid(D) ? "true" : "false") + - ",\"source_a_bits\":" + std::to_string(forms[static_cast(pos)].a.num_bits()) + "}"); - // #endregion - } - if (power >= 12644100 && power <= 12644300) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H40", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h40_source_state", - "H40 window source form state before copy", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"source_valid\":" + (forms[static_cast(pos)].check_valid(D) ? "true" : "false") + - ",\"source_a_bits\":" + std::to_string(forms[static_cast(pos)].a.num_bits()) + "}"); - // #endregion - } - if (power >= 12635000 && power <= 12635200) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H41", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h41_stage0_before_source_deref", - "H41 stage0 before source dereference", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + "}"); - // #endregion - form& source = forms[static_cast(pos)]; - const bool source_valid = source.check_valid(D); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H41", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h41_stage1_after_check_valid", - "H41 stage1 after check_valid", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"source_valid\":" + (source_valid ? "true" : "false") + "}"); - // #endregion - const uint64_t source_a_bits = static_cast(source.a.num_bits()); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H41", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h41_stage2_after_num_bits", - "H41 stage2 after source num_bits", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"source_a_bits\":" + std::to_string(source_a_bits) + "}"); - // #endregion - } - if (power >= 12602010 && power <= 12602400) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H42", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h42_stage0_before_source_deref", - "H42 stage0 before source dereference", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + "}"); - // #endregion - form& source = forms[static_cast(pos)]; - const bool source_valid = source.check_valid(D); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H42", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h42_stage1_after_check_valid", - "H42 stage1 after check_valid", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"source_valid\":" + (source_valid ? "true" : "false") + "}"); - // #endregion - const uint64_t source_a_bits = static_cast(source.a.num_bits()); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H42", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h42_stage2_after_num_bits", - "H42 stage2 after source num_bits", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"source_a_bits\":" + std::to_string(source_a_bits) + "}"); - // #endregion - } - if (power >= 12642010 && power <= 12642400) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H43", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h43_stage0_before_source_deref", - "H43 stage0 before source dereference", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + "}"); - // #endregion - form& source = forms[static_cast(pos)]; - const uint64_t source_a_bits = static_cast(source.a.num_bits()); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H43", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h43_stage1_after_num_bits", - "H43 stage1 after source num_bits", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"source_a_bits\":" + std::to_string(source_a_bits) + "}"); - // #endregion - } - if (power >= 12500010 && power <= 12500600) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H44", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h44_stage0_before_source_deref", - "H44 stage0 before source dereference", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + "}"); - // #endregion - form& source = forms[static_cast(pos)]; - const uint64_t source_a_bits = static_cast(source.a.num_bits()); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H44", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h44_stage1_after_num_bits", - "H44 stage1 after source num_bits", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"source_a_bits\":" + std::to_string(source_a_bits) + "}"); - // #endregion - } - if (power >= 12607010 && power <= 12607600) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H45", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h45_stage0_before_source_deref", - "H45 stage0 before source dereference", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + "}"); - // #endregion - form& source = forms[static_cast(pos)]; - const uint64_t source_a_bits = static_cast(source.a.num_bits()); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H45", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h45_stage1_after_num_bits", - "H45 stage1 after source num_bits", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"source_a_bits\":" + std::to_string(source_a_bits) + "}"); - // #endregion - } - if (power >= 12500610 && power <= 12501200) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H46", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h46_stage0_before_source_deref", - "H46 stage0 before source dereference", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + "}"); - // #endregion - form& source = forms[static_cast(pos)]; - const uint64_t source_a_bits = static_cast(source.a.num_bits()); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H46", - "callback.h:TwoWesolowskiCallback:GetFormCopy_h46_stage1_after_num_bits", - "H46 stage1 after source num_bits", - std::string("{\"power\":") + std::to_string(power) + - ",\"pos\":" + std::to_string(pos) + - ",\"source_a_bits\":" + std::to_string(source_a_bits) + "}"); - // #endregion - } return forms[static_cast(pos)]; } @@ -693,64 +166,12 @@ class TwoWesolowskiCallback: public WesolowskiCallback { iteration++; if (iteration % kl == 0) { const int pos = GetPosition(iteration); - if (iteration >= 12647080 && iteration <= 12647220) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H39", - "callback.h:TwoWesolowskiCallback:OnIteration_h39_before_setform", - "H39 producer before SetForm", - std::string("{\"iteration\":") + std::to_string(iteration) + - ",\"pos\":" + std::to_string(pos) + - ",\"forms_capacity\":" + std::to_string(forms_capacity) + "}"); - // #endregion - } - if (iteration % 1000000 == 0) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H19", - "callback.h:TwoWesolowskiCallback:OnIteration_progress", - "OnIteration progress marker", - std::string("{\"iteration\":") + std::to_string(iteration) + - ",\"pos\":" + std::to_string(pos) + - ",\"forms_capacity\":" + std::to_string(forms_capacity) + - ",\"kl\":" + std::to_string(kl) + - ",\"switch_iters\":" + std::to_string(switch_iters) + "}"); - // #endregion - } if (pos < 0 || static_cast(pos) >= forms_capacity) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H19", - "callback.h:TwoWesolowskiCallback:OnIteration_oob", - "OnIteration write position out of bounds", - std::string("{\"iteration\":") + std::to_string(iteration) + - ",\"pos\":" + std::to_string(pos) + - ",\"forms_capacity\":" + std::to_string(forms_capacity) + - ",\"kl\":" + std::to_string(kl) + - ",\"switch_iters\":" + std::to_string(switch_iters) + - ",\"switch_index\":" + std::to_string(switch_index) + "}"); - // #endregion throw std::runtime_error("TwoWesolowskiCallback::OnIteration out of bounds"); } std::lock_guard lk(forms_mutex); form* mulf = &forms[static_cast(pos)]; SetForm(type, data, mulf); - if (iteration >= 12647080 && iteration <= 12647220) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H39", - "callback.h:TwoWesolowskiCallback:OnIteration_h39_after_setform", - "H39 producer after SetForm", - std::string("{\"iteration\":") + std::to_string(iteration) + - ",\"pos\":" + std::to_string(pos) + - ",\"stored_valid\":" + (mulf->check_valid(D) ? "true" : "false") + - ",\"stored_a_bits\":" + std::to_string(mulf->a.num_bits()) + "}"); - // #endregion - } } } diff --git a/src/prover_base.hpp b/src/prover_base.hpp index 54e27056..27700f37 100644 --- a/src/prover_base.hpp +++ b/src/prover_base.hpp @@ -7,8 +7,6 @@ #include "proof_common.h" #include "util.h" -#define ProverAgentDebugLog(...) do {} while (0) - class Prover { public: Prover(Segment segm, integer D) { @@ -41,18 +39,6 @@ class Prover { } void GenerateProof() { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H15", - "prover_base.hpp:Prover:GenerateProof_enter", - "GenerateProof enter", - std::string("{\"num_iterations\":") + std::to_string(num_iterations) + - ",\"k\":" + std::to_string(k) + - ",\"l\":" + std::to_string(l) + - ",\"seg_start\":" + std::to_string(segm.start) + - ",\"seg_length\":" + std::to_string(segm.length) + "}"); - // #endregion PulmarkReducer reducer; integer B = GetB(D, segm.x, segm.y); @@ -69,14 +55,6 @@ class Prover { return ; } - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H15", - "prover_base.hpp:Prover:GenerateProof_after_identity", - "Identity setup complete", - "{}"); - // #endregion uint64_t k1 = k / 2; uint64_t k0 = k - k1; form x = id; @@ -92,1171 +70,19 @@ class Prover { uint64_t limit = num_iterations / (k * l); if (num_iterations % (k * l)) limit++; - // #region agent log - if (j == static_cast(l - 1)) { - ProverAgentDebugLog( - "post-fix", - "H15", - "prover_base.hpp:Prover:GenerateProof_first_round", - "First outer round setup", - std::string("{\"j\":") + std::to_string(j) + - ",\"limit\":" + std::to_string(limit) + "}"); - } - // #endregion for (uint64_t i = 0; i < limit; i++) { if (num_iterations >= k * (i * l + j + 1)) { - if (segm.start >= 10000000 && j == 0 && i >= 264300 && i <= 264700) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H33", - "prover_base.hpp:Prover:GenerateProof_boundary_iter_enter", - "Boundary window iteration enter", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"limit\":" + std::to_string(limit) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264430 && i <= 264432) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H34", - "prover_base.hpp:Prover:GenerateProof_iter_before_getblock", - "Focused window before GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264701 && i <= 264760) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H35", - "prover_base.hpp:Prover:GenerateProof_post700_before_getblock", - "Post-264700 focused window before GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 269980 && i <= 270060) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H36", - "prover_base.hpp:Prover:GenerateProof_270k_before_getblock", - "270k window before GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264318 && i <= 264324) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H38", - "prover_base.hpp:Prover:GenerateProof_crash_window_before_getblock", - "Crash-window before GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264410 && i <= 264430) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H40", - "prover_base.hpp:Prover:GenerateProof_h40_before_getblock", - "H40 window before GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 263500 && i <= 263520) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H41", - "prover_base.hpp:Prover:GenerateProof_h41_before_getblock", - "H41 window before GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260201 && i <= 260240) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H42", - "prover_base.hpp:Prover:GenerateProof_h42_before_getblock", - "H42 micro window before GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264201 && i <= 264240) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H43", - "prover_base.hpp:Prover:GenerateProof_h43_before_getblock", - "H43 micro window before GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 250001 && i <= 250060) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H44", - "prover_base.hpp:Prover:GenerateProof_h44_before_getblock", - "H44 micro window before GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260701 && i <= 260760) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H45", - "prover_base.hpp:Prover:GenerateProof_h45_before_getblock", - "H45 micro window before GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 250061 && i <= 250120) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H46", - "prover_base.hpp:Prover:GenerateProof_h46_before_getblock", - "H46 micro window before GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260000 && i <= 265000 && (i % 100 == 0)) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H29", - "prover_base.hpp:Prover:GenerateProof_tail_before_getblock", - "Tail window before GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"num_iterations\":" + std::to_string(num_iterations) + "}"); - // #endregion - } uint64_t b = GetBlock(i*l + j, k, num_iterations, B); - if (segm.start >= 10000000 && j == 0 && i >= 264430 && i <= 264432) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H34", - "prover_base.hpp:Prover:GenerateProof_iter_after_getblock", - "Focused window after GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264701 && i <= 264760) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H35", - "prover_base.hpp:Prover:GenerateProof_post700_after_getblock", - "Post-264700 focused window after GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 269980 && i <= 270060) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H36", - "prover_base.hpp:Prover:GenerateProof_270k_after_getblock", - "270k window after GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264318 && i <= 264324) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H38", - "prover_base.hpp:Prover:GenerateProof_crash_window_after_getblock", - "Crash-window after GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264410 && i <= 264430) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H40", - "prover_base.hpp:Prover:GenerateProof_h40_after_getblock", - "H40 window after GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 263500 && i <= 263520) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H41", - "prover_base.hpp:Prover:GenerateProof_h41_after_getblock", - "H41 window after GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260201 && i <= 260240) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H42", - "prover_base.hpp:Prover:GenerateProof_h42_after_getblock", - "H42 micro window after GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264201 && i <= 264240) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H43", - "prover_base.hpp:Prover:GenerateProof_h43_after_getblock", - "H43 micro window after GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 250001 && i <= 250060) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H44", - "prover_base.hpp:Prover:GenerateProof_h44_after_getblock", - "H44 micro window after GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260701 && i <= 260760) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H45", - "prover_base.hpp:Prover:GenerateProof_h45_after_getblock", - "H45 micro window after GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 250061 && i <= 250120) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H46", - "prover_base.hpp:Prover:GenerateProof_h46_after_getblock", - "H46 micro window after GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"b_in_range\":" + ((b < (1UL << k)) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 265001 && i <= 265200) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H30", - "prover_base.hpp:Prover:GenerateProof_micro_after_getblock", - "Micro window after GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260000 && i <= 265000 && (i % 100 == 0)) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H29", - "prover_base.hpp:Prover:GenerateProof_tail_after_getblock", - "Tail window after GetBlock", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } if (b >= (1UL << k)) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H18", - "prover_base.hpp:Prover:GenerateProof_block_oob", - "Computed block index out of bounds", - std::string("{\"b\":") + std::to_string(b) + - ",\"k\":" + std::to_string(k) + - ",\"i\":" + std::to_string(i) + - ",\"j\":" + std::to_string(j) + - ",\"num_iterations\":" + std::to_string(num_iterations) + "}"); - // #endregion throw std::runtime_error("GenerateProof block index out of bounds"); } if (!PerformExtraStep()) return; - if (segm.start >= 10000000 && j == 0 && i >= 265001 && i <= 265200) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H30", - "prover_base.hpp:Prover:GenerateProof_micro_after_extra_step", - "Micro window after PerformExtraStep", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260000 && i <= 265000 && (i % 100 == 0)) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H28", - "prover_base.hpp:Prover:GenerateProof_tail_before_getform", - "Tail window before GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && (i % 50000 == 0)) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H24", - "prover_base.hpp:Prover:GenerateProof_progress_before_getform", - "Long GenerateProof progress before GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"limit\":" + std::to_string(limit) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - // #region agent log - if (j == static_cast(l - 1) && i == 0) { - ProverAgentDebugLog( - "post-fix", - "H15", - "prover_base.hpp:Prover:GenerateProof_before_first_getform", - "About to fetch first intermediate form", - std::string("{\"block\":") + std::to_string(b) + "}"); - } - // #endregion - if (segm.start >= 10000000 && j == 0 && i >= 265001 && i <= 265200) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H32", - "prover_base.hpp:Prover:GenerateProof_micro_before_getform_call", - "Micro window immediately before GetForm call", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264430 && i <= 264432) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H34", - "prover_base.hpp:Prover:GenerateProof_iter_before_getform", - "Focused window before GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264701 && i <= 264760) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H35", - "prover_base.hpp:Prover:GenerateProof_post700_before_getform", - "Post-264700 focused window before GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 269980 && i <= 270060) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H36", - "prover_base.hpp:Prover:GenerateProof_270k_before_getform", - "270k window before GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264318 && i <= 264324) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H38", - "prover_base.hpp:Prover:GenerateProof_crash_window_before_getform", - "Crash-window before GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264410 && i <= 264430) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H40", - "prover_base.hpp:Prover:GenerateProof_h40_before_getform", - "H40 window before GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260201 && i <= 260240) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H42", - "prover_base.hpp:Prover:GenerateProof_h42_before_getform", - "H42 micro window before GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264201 && i <= 264240) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H43", - "prover_base.hpp:Prover:GenerateProof_h43_before_getform", - "H43 micro window before GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 250001 && i <= 250060) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H44", - "prover_base.hpp:Prover:GenerateProof_h44_before_getform", - "H44 micro window before GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260701 && i <= 260760) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H45", - "prover_base.hpp:Prover:GenerateProof_h45_before_getform", - "H45 micro window before GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 250061 && i <= 250120) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H46", - "prover_base.hpp:Prover:GenerateProof_h46_before_getform", - "H46 micro window before GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 230000 && i <= 230200) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H52", - "prover_base.hpp:Prover:GenerateProof_h52_before_getform", - "H52 focused window before GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } tmp = GetForm(i); - if (segm.start >= 10000000 && j == 0 && i >= 264430 && i <= 264432) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H34", - "prover_base.hpp:Prover:GenerateProof_iter_after_getform", - "Focused window after GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + - ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264701 && i <= 264760) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H35", - "prover_base.hpp:Prover:GenerateProof_post700_after_getform", - "Post-264700 focused window after GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + - ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 269980 && i <= 270060) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H36", - "prover_base.hpp:Prover:GenerateProof_270k_after_getform", - "270k window after GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + - ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264318 && i <= 264324) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H38", - "prover_base.hpp:Prover:GenerateProof_crash_window_after_getform", - "Crash-window after GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + - ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264410 && i <= 264430) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H40", - "prover_base.hpp:Prover:GenerateProof_h40_after_getform", - "H40 window after GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + - ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260201 && i <= 260240) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H42", - "prover_base.hpp:Prover:GenerateProof_h42_after_getform", - "H42 micro window after GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + - ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264201 && i <= 264240) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H43", - "prover_base.hpp:Prover:GenerateProof_h43_after_getform", - "H43 micro window after GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + - ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 250001 && i <= 250060) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H44", - "prover_base.hpp:Prover:GenerateProof_h44_after_getform", - "H44 micro window after GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + - ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260701 && i <= 260760) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H45", - "prover_base.hpp:Prover:GenerateProof_h45_after_getform", - "H45 micro window after GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + - ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 250061 && i <= 250120) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H46", - "prover_base.hpp:Prover:GenerateProof_h46_after_getform", - "H46 micro window after GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + - ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 230000 && i <= 230200) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H52", - "prover_base.hpp:Prover:GenerateProof_h52_after_getform", - "H52 focused window after GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + - ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 265001 && i <= 265200) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H30", - "prover_base.hpp:Prover:GenerateProof_micro_after_getform", - "Micro window after GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260000 && i <= 265000 && (i % 100 == 0)) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H28", - "prover_base.hpp:Prover:GenerateProof_tail_after_getform", - "Tail window after GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && (i % 50000 == 0)) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H24", - "prover_base.hpp:Prover:GenerateProof_progress_after_getform", - "Long GenerateProof progress after GetForm", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - // #region agent log - if (j == static_cast(l - 1) && i == 0) { - ProverAgentDebugLog( - "post-fix", - "H15", - "prover_base.hpp:Prover:GenerateProof_after_first_getform", - "Fetched first intermediate form", - "{}"); - } - // #endregion - if (segm.start >= 10000000 && j == 0 && (i % 10000 == 0)) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H26", - "prover_base.hpp:Prover:GenerateProof_before_nucomp_fine", - "Fine-grained long GenerateProof before nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + - ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + - ",\"tmp_a_bits\":" + std::to_string(tmp->a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260000 && i <= 265000 && (i % 100 == 0)) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H28", - "prover_base.hpp:Prover:GenerateProof_tail_before_nucomp", - "Tail window before nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264430 && i <= 264432) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H34", - "prover_base.hpp:Prover:GenerateProof_iter_before_nucomp", - "Focused window before nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264701 && i <= 264760) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H35", - "prover_base.hpp:Prover:GenerateProof_post700_before_nucomp", - "Post-264700 focused window before nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 269980 && i <= 270060) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H36", - "prover_base.hpp:Prover:GenerateProof_270k_before_nucomp", - "270k window before nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264318 && i <= 264324) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H38", - "prover_base.hpp:Prover:GenerateProof_crash_window_before_nucomp", - "Crash-window before nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264410 && i <= 264430) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H40", - "prover_base.hpp:Prover:GenerateProof_h40_before_nucomp", - "H40 window before nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260201 && i <= 260240) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H42", - "prover_base.hpp:Prover:GenerateProof_h42_before_nucomp", - "H42 micro window before nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264201 && i <= 264240) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H43", - "prover_base.hpp:Prover:GenerateProof_h43_before_nucomp", - "H43 micro window before nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 250001 && i <= 250060) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H44", - "prover_base.hpp:Prover:GenerateProof_h44_before_nucomp", - "H44 micro window before nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260701 && i <= 260760) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H45", - "prover_base.hpp:Prover:GenerateProof_h45_before_nucomp", - "H45 micro window before nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 250061 && i <= 250120) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H46", - "prover_base.hpp:Prover:GenerateProof_h46_before_nucomp", - "H46 micro window before nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"tmp_valid\":" + (tmp->check_valid(D) ? "true" : "false") + "}"); - // #endregion - } nucomp_form(ys[b], ys[b], *tmp, D, L); - if (segm.start >= 10000000 && j == 0 && i >= 264430 && i <= 264432) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H34", - "prover_base.hpp:Prover:GenerateProof_iter_after_nucomp", - "Focused window after nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 230000 && i <= 230200) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H52", - "prover_base.hpp:Prover:GenerateProof_h52_after_nucomp", - "H52 focused window after nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264701 && i <= 264760) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H35", - "prover_base.hpp:Prover:GenerateProof_post700_after_nucomp", - "Post-264700 focused window after nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 269980 && i <= 270060) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H36", - "prover_base.hpp:Prover:GenerateProof_270k_after_nucomp", - "270k window after nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264318 && i <= 264324) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H38", - "prover_base.hpp:Prover:GenerateProof_crash_window_after_nucomp", - "Crash-window after nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264410 && i <= 264430) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H40", - "prover_base.hpp:Prover:GenerateProof_h40_after_nucomp", - "H40 window after nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 263500 && i <= 263520) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H41", - "prover_base.hpp:Prover:GenerateProof_h41_after_nucomp", - "H41 window after nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260201 && i <= 260240) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H42", - "prover_base.hpp:Prover:GenerateProof_h42_after_nucomp", - "H42 micro window after nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264201 && i <= 264240) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H43", - "prover_base.hpp:Prover:GenerateProof_h43_after_nucomp", - "H43 micro window after nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 250001 && i <= 250060) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H44", - "prover_base.hpp:Prover:GenerateProof_h44_after_nucomp", - "H44 micro window after nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260701 && i <= 260760) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H45", - "prover_base.hpp:Prover:GenerateProof_h45_after_nucomp", - "H45 micro window after nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 250061 && i <= 250120) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H46", - "prover_base.hpp:Prover:GenerateProof_h46_after_nucomp", - "H46 micro window after nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 265001 && i <= 265200) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H30", - "prover_base.hpp:Prover:GenerateProof_micro_after_nucomp", - "Micro window after nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260000 && i <= 265000 && (i % 100 == 0)) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H28", - "prover_base.hpp:Prover:GenerateProof_tail_after_nucomp", - "Tail window after nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && (i % 10000 == 0)) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H26", - "prover_base.hpp:Prover:GenerateProof_after_nucomp_fine", - "Fine-grained long GenerateProof after nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && (i % 50000 == 0)) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H24", - "prover_base.hpp:Prover:GenerateProof_progress_after_nucomp", - "Long GenerateProof progress after nucomp_form", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"b\":" + std::to_string(b) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 260000 && (i % 5000 == 0)) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H27", - "prover_base.hpp:Prover:GenerateProof_tail_progress", - "Long GenerateProof tail progress marker", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"limit\":" + std::to_string(limit) + "}"); - // #endregion - } - if (segm.start >= 10000000 && j == 0 && i >= 264300 && i <= 264700) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H33", - "prover_base.hpp:Prover:GenerateProof_boundary_iter_exit", - "Boundary window iteration exit", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"i\":" + std::to_string(i) + - ",\"ys_valid\":" + (ys[b].check_valid(D) ? "true" : "false") + - ",\"ys_a_bits\":" + std::to_string(ys[b].a.num_bits()) + "}"); - // #endregion - } } } - if (segm.start >= 10000000 && j == 0) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H27", - "prover_base.hpp:Prover:GenerateProof_after_collect_phase", - "Completed long GenerateProof collect phase", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"limit\":" + std::to_string(limit) + "}"); - // #endregion - } for (uint64_t b1 = 0; b1 < (1UL << k1); b1++) { - if (segm.start >= 10000000 && j == 0 && (b1 % 16 == 0)) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H27", - "prover_base.hpp:Prover:GenerateProof_phase2_progress", - "Long GenerateProof phase2 progress", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"b1\":" + std::to_string(b1) + "}"); - // #endregion - } form z = id; for (uint64_t b0 = 0; b0 < (1UL << k0); b0++) { if (!PerformExtraStep()) return; @@ -1265,29 +91,8 @@ class Prover { z = FastPowFormNucomp(z, D, integer(b1 * (1 << k0)), L, reducer); nucomp_form(x, x, z, D, L); } - if (segm.start >= 10000000 && j == 0) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H27", - "prover_base.hpp:Prover:GenerateProof_after_phase2", - "Completed long GenerateProof phase2", - std::string("{\"seg_start\":") + std::to_string(segm.start) + "}"); - // #endregion - } for (uint64_t b0 = 0; b0 < (1UL << k0); b0++) { - if (segm.start >= 10000000 && j == 0 && (b0 % 16 == 0)) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H27", - "prover_base.hpp:Prover:GenerateProof_phase3_progress", - "Long GenerateProof phase3 progress", - std::string("{\"seg_start\":") + std::to_string(segm.start) + - ",\"b0\":" + std::to_string(b0) + "}"); - // #endregion - } form z = id; for (uint64_t b1 = 0; b1 < (1UL << k1); b1++) { if (!PerformExtraStep()) return; @@ -1296,28 +101,10 @@ class Prover { z = FastPowFormNucomp(z, D, integer(b0), L, reducer); nucomp_form(x, x, z, D, L); } - if (segm.start >= 10000000 && j == 0) { - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H27", - "prover_base.hpp:Prover:GenerateProof_after_phase3", - "Completed long GenerateProof phase3", - std::string("{\"seg_start\":") + std::to_string(segm.start) + "}"); - // #endregion - } } reducer.reduce(x); proof = x; OnFinish(); - // #region agent log - ProverAgentDebugLog( - "post-fix", - "H15", - "prover_base.hpp:Prover:GenerateProof_exit", - "GenerateProof finished", - "{}"); - // #endregion } protected: diff --git a/src/provers.h b/src/provers.h index 839d6843..255d98ca 100644 --- a/src/provers.h +++ b/src/provers.h @@ -54,522 +54,17 @@ class TwoWesolowskiProver : public Prover{ } void start() { - // #region agent log - CallbackAgentDebugLog("post-fix", "H14", "provers.h:TwoWesolowskiProver:start_enter", "TwoWesolowskiProver start called", "{}"); - // #endregion try { std::thread t([=] { GenerateProof(); }); t.detach(); - // #region agent log - CallbackAgentDebugLog("post-fix", "H14", "provers.h:TwoWesolowskiProver:start_detached", "Prover thread created and detached", "{}"); - // #endregion } catch (const std::system_error& e) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H14", - "provers.h:TwoWesolowskiProver:start_fallback_inline", - "Thread creation failed, running inline", - std::string("{\"what\":\"") + e.what() + "\"}"); - // #endregion GenerateProof(); } } virtual form* GetForm(uint64_t i) { const uint64_t power = done_iterations + i * k * l; - const int64_t produced = weso->iterations.load(std::memory_order_relaxed); - if (done_iterations >= 10000000 && (i % 50000 == 0)) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H25", - "provers.h:TwoWesolowskiProver:GetForm_progress", - "Long prover GetForm progress", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + - ",\"k\":" + std::to_string(k) + - ",\"l\":" + std::to_string(l) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 260000 && i <= 265000 && (i % 100 == 0)) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H29", - "provers.h:TwoWesolowskiProver:GetForm_tail_window", - "Tail window prover GetForm details", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + - ",\"k\":" + std::to_string(k) + - ",\"l\":" + std::to_string(l) + "}"); - // #endregion - } - if (power > static_cast(produced)) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H22", - "provers.h:TwoWesolowskiProver:GetForm_read_ahead", - "Requested form ahead of produced iterations", - std::string("{\"power\":") + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + - ",\"done_iterations\":" + std::to_string(done_iterations) + - ",\"k\":" + std::to_string(k) + - ",\"l\":" + std::to_string(l) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 265001 && i <= 265200) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H30", - "provers.h:TwoWesolowskiProver:GetForm_micro_before_copy", - "Micro window before GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 264430 && i <= 264432) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H34", - "provers.h:TwoWesolowskiProver:GetForm_focused_before_copy", - "Focused window before GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 264701 && i <= 264760) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H35", - "provers.h:TwoWesolowskiProver:GetForm_post700_before_copy", - "Post-264700 focused window before GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 269980 && i <= 270060) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H36", - "provers.h:TwoWesolowskiProver:GetForm_270k_before_copy", - "270k window before GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 264318 && i <= 264324) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H38", - "provers.h:TwoWesolowskiProver:GetForm_crash_window_before_copy", - "Crash-window before GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 264410 && i <= 264430) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H40", - "provers.h:TwoWesolowskiProver:GetForm_h40_before_copy", - "H40 window before GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 263500 && i <= 263520) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H41", - "provers.h:TwoWesolowskiProver:GetForm_h41_before_copy", - "H41 window before GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 260201 && i <= 260240) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H42", - "provers.h:TwoWesolowskiProver:GetForm_h42_before_copy", - "H42 micro window before GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 264201 && i <= 264240) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H43", - "provers.h:TwoWesolowskiProver:GetForm_h43_before_copy", - "H43 micro window before GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 250001 && i <= 250060) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H44", - "provers.h:TwoWesolowskiProver:GetForm_h44_before_copy", - "H44 micro window before GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 260701 && i <= 260760) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H45", - "provers.h:TwoWesolowskiProver:GetForm_h45_before_copy", - "H45 micro window before GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 250061 && i <= 250120) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H46", - "provers.h:TwoWesolowskiProver:GetForm_h46_before_copy", - "H46 micro window before GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 250058 && i <= 250062) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H47", - "provers.h:TwoWesolowskiProver:GetForm_h47_before_copy", - "H47 tight boundary before GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 250090 && i <= 250100) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H50", - "provers.h:TwoWesolowskiProver:GetForm_h50_before_copy", - "H50 boundary before GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 250061 && i <= 250063) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H51", - "provers.h:TwoWesolowskiProver:GetForm_h51_before_copy", - "H51 boundary before GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 250030 && i <= 250040) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H49", - "provers.h:TwoWesolowskiProver:GetForm_h49_before_copy", - "H49 boundary before GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"produced_iterations\":" + std::to_string(produced) + - ",\"weso_ptr\":" + - std::to_string(static_cast(reinterpret_cast(weso))) + "}"); - // #endregion - } cached_form = weso->GetFormCopy(power); - if (done_iterations >= 10000000 && i >= 264430 && i <= 264432) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H34", - "provers.h:TwoWesolowskiProver:GetForm_focused_after_copy", - "Focused window after GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + - ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 264701 && i <= 264760) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H35", - "provers.h:TwoWesolowskiProver:GetForm_post700_after_copy", - "Post-264700 focused window after GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + - ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 269980 && i <= 270060) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H36", - "provers.h:TwoWesolowskiProver:GetForm_270k_after_copy", - "270k window after GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + - ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 264410 && i <= 264430) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H40", - "provers.h:TwoWesolowskiProver:GetForm_h40_after_copy", - "H40 window after GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + - ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 264318 && i <= 264324) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H38", - "provers.h:TwoWesolowskiProver:GetForm_crash_window_after_copy", - "Crash-window after GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + - ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 263500 && i <= 263520) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H41", - "provers.h:TwoWesolowskiProver:GetForm_h41_after_copy", - "H41 window after GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + - ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 260201 && i <= 260240) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H42", - "provers.h:TwoWesolowskiProver:GetForm_h42_after_copy", - "H42 micro window after GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + - ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 264201 && i <= 264240) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H43", - "provers.h:TwoWesolowskiProver:GetForm_h43_after_copy", - "H43 micro window after GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + - ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 250001 && i <= 250060) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H44", - "provers.h:TwoWesolowskiProver:GetForm_h44_after_copy", - "H44 micro window after GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + - ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 260701 && i <= 260760) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H45", - "provers.h:TwoWesolowskiProver:GetForm_h45_after_copy", - "H45 micro window after GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + - ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 250061 && i <= 250120) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H46", - "provers.h:TwoWesolowskiProver:GetForm_h46_after_copy", - "H46 micro window after GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + - ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 250058 && i <= 250062) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H47", - "provers.h:TwoWesolowskiProver:GetForm_h47_after_copy", - "H47 tight boundary after GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + - ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 250090 && i <= 250100) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H50", - "provers.h:TwoWesolowskiProver:GetForm_h50_after_copy", - "H50 boundary after GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + - ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 250061 && i <= 250063) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H51", - "provers.h:TwoWesolowskiProver:GetForm_h51_after_copy", - "H51 boundary after GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + - ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 250030 && i <= 250040) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H49", - "provers.h:TwoWesolowskiProver:GetForm_h49_after_copy", - "H49 boundary after GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + - ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 265001 && i <= 265200) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H30", - "provers.h:TwoWesolowskiProver:GetForm_micro_after_copy", - "Micro window after GetFormCopy", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + "}"); - // #endregion - } - if (done_iterations >= 10000000 && i >= 265001 && i <= 265200) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H32", - "provers.h:TwoWesolowskiProver:GetForm_micro_before_return", - "Micro window before returning cached form pointer", - std::string("{\"done_iterations\":") + std::to_string(done_iterations) + - ",\"i\":" + std::to_string(i) + - ",\"power\":" + std::to_string(power) + - ",\"cached_valid\":" + (cached_form.check_valid(D) ? "true" : "false") + - ",\"cached_a_bits\":" + std::to_string(cached_form.a.num_bits()) + "}"); - // #endregion - } return &cached_form; } diff --git a/src/vdf.h b/src/vdf.h index af9673cb..d0f5af47 100644 --- a/src/vdf.h +++ b/src/vdf.h @@ -132,126 +132,25 @@ static inline void repeated_square_nudupl( } for (uint64_t i = 0; i < iterations; i++) { const uint64_t current_iter = base + i + 1; - if (two_weso && current_iter >= 13860000 && current_iter <= 13920000 && (current_iter % 500 == 0)) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H33", - "vdf.h:repeated_square_nudupl:before_nudupl", - "NUDUPL worker micro window before nudupl_form", - std::string("{\"current_iter\":") + std::to_string(current_iter) + "}"); - // #endregion - } - if (two_weso && current_iter >= 13891000 && current_iter <= 13893000 && (current_iter % 100 == 0)) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H35", - "vdf.h:repeated_square_nudupl:post700_before_nudupl", - "Post-13891000 focused worker window before nudupl_form", - std::string("{\"current_iter\":") + std::to_string(current_iter) + "}"); - // #endregion - } - if (two_weso && current_iter >= 13885500 && current_iter <= 13887500 && (current_iter % 100 == 0)) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H36", - "vdf.h:repeated_square_nudupl:270k_before_nudupl", - "270k-correlated worker window before nudupl_form", - std::string("{\"current_iter\":") + std::to_string(current_iter) + "}"); - // #endregion - } nudupl_form(f, f, D, L); - if (two_weso && current_iter >= 13860000 && current_iter <= 13920000 && (current_iter % 500 == 0)) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H33", - "vdf.h:repeated_square_nudupl:after_nudupl", - "NUDUPL worker micro window after nudupl_form", - std::string("{\"current_iter\":") + std::to_string(current_iter) + "}"); - // #endregion - } - if (two_weso && current_iter >= 13891000 && current_iter <= 13893000 && (current_iter % 100 == 0)) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H35", - "vdf.h:repeated_square_nudupl:post700_after_nudupl", - "Post-13891000 focused worker window after nudupl_form", - std::string("{\"current_iter\":") + std::to_string(current_iter) + "}"); - // #endregion - } - if (two_weso && current_iter >= 13885500 && current_iter <= 13887500 && (current_iter % 100 == 0)) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H36", - "vdf.h:repeated_square_nudupl:270k_after_nudupl", - "270k-correlated worker window after nudupl_form", - std::string("{\"current_iter\":") + std::to_string(current_iter) + "}"); - // #endregion - } // Reduce only when `a` grows beyond a small limb threshold. Reducing every iteration // can be slower than letting NUDUPL run a bit "wide". if (__GMP_ABS(f.a.impl->_mp_size) > 8) { - if (two_weso && current_iter >= 13885500 && current_iter <= 13887500 && (current_iter % 100 == 0)) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H36", - "vdf.h:repeated_square_nudupl:270k_before_reduce", - "270k-correlated worker window before reduce", - std::string("{\"current_iter\":") + std::to_string(current_iter) + - ",\"a_limb_size\":" + std::to_string(__GMP_ABS(f.a.impl->_mp_size)) + "}"); - // #endregion - } if (weso) { weso->reduce(f); } else { fallback_reducer->reduce(f); } - if (two_weso && current_iter >= 13885500 && current_iter <= 13887500 && (current_iter % 100 == 0)) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H36", - "vdf.h:repeated_square_nudupl:270k_after_reduce", - "270k-correlated worker window after reduce", - std::string("{\"current_iter\":") + std::to_string(current_iter) + "}"); - // #endregion - } } if (nuduplListener != nullptr) { - if (two_weso && current_iter >= 13885500 && current_iter <= 13887500 && (current_iter % 100 == 0)) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H36", - "vdf.h:repeated_square_nudupl:270k_before_oniteration", - "270k-correlated worker window before OnIteration callback", - std::string("{\"current_iter\":") + std::to_string(current_iter) + "}"); - // #endregion - } // Present the C++ `form` as a `vdf_original::form` view so existing callbacks can // consume it without any new type tags. f_view.a[0] = f.a.impl[0]; f_view.b[0] = f.b.impl[0]; f_view.c[0] = f.c.impl[0]; nuduplListener->OnIteration(NL_FORM, &f_view, base + i); - if (two_weso && current_iter >= 13885500 && current_iter <= 13887500 && (current_iter % 100 == 0)) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H36", - "vdf.h:repeated_square_nudupl:270k_after_oniteration", - "270k-correlated worker window after OnIteration callback", - std::string("{\"current_iter\":") + std::to_string(current_iter) + "}"); - // #endregion - } } } } @@ -268,8 +167,6 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege uint64_t num_iterations = 0; uint64_t last_checkpoint = 0; - uint64_t debug_progress_mark = 12000000; - uint64_t debug_fast_call_mark = 13500000; while (!stopped) { uint64 c_checkpoint_interval=checkpoint_interval; @@ -301,30 +198,7 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege // x86/x64: use the phased pipeline. square_state_type square_state; square_state.pairindex = 0; - if (two_weso && num_iterations >= debug_fast_call_mark) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H21", - "vdf.h:repeated_square:before_fast_call", - "About to call repeated_square_fast", - std::string("{\"num_iterations\":") + std::to_string(num_iterations) + - ",\"batch_size\":" + std::to_string(batch_size) + "}"); - // #endregion - } actual_iterations = repeated_square_fast(square_state, f, D, L, num_iterations, batch_size, weso); - if (two_weso && num_iterations >= debug_fast_call_mark) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H21", - "vdf.h:repeated_square:after_fast_call", - "repeated_square_fast returned", - std::string("{\"num_iterations\":") + std::to_string(num_iterations) + - ",\"actual_iterations\":" + std::to_string(actual_iterations) + "}"); - // #endregion - debug_fast_call_mark += 100000; - } #else // Non-x86: use the C++ NUDUPL path (faster and lower maintenance than the phased pipeline). integer& D_nc = const_cast(D); @@ -375,19 +249,6 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege } num_iterations+=actual_iterations; - if (two_weso && num_iterations >= debug_progress_mark) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H20", - "vdf.h:repeated_square:progress", - "repeated_square progress marker", - std::string("{\"num_iterations\":") + std::to_string(num_iterations) + - ",\"actual_iterations\":" + std::to_string(actual_iterations) + - ",\"batch_size\":" + std::to_string(batch_size) + "}"); - // #endregion - debug_progress_mark += 500000; - } if (num_iterations >= last_checkpoint) { weso->iterations = num_iterations; @@ -491,59 +352,17 @@ Proof ProveOneWesolowski(uint64_t iters, integer& D, form f, OneWesolowskiCallba Proof ProveTwoWeso(integer& D, form x, uint64_t iters, uint64_t done_iterations, TwoWesolowskiCallback* weso, int depth, std::atomic& stop_signal) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H17", - "vdf.h:ProveTwoWeso:enter", - "Enter ProveTwoWeso", - std::string("{\"depth\":") + std::to_string(depth) + - ",\"iters\":" + std::to_string(iters) + - ",\"done_iterations\":" + std::to_string(done_iterations) + "}"); - // #endregion integer L=root(-D, 4); if (depth == 2) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H17", - "vdf.h:ProveTwoWeso:depth2_before_wait", - "Depth-2 waiting for required iterations", - std::string("{\"target\":") + std::to_string(done_iterations + iters) + "}"); - // #endregion while (!stop_signal && weso->iterations < done_iterations + iters) { std::this_thread::sleep_for (std::chrono::milliseconds(200)); } - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H17", - "vdf.h:ProveTwoWeso:depth2_after_wait", - "Depth-2 wait completed", - std::string("{\"iterations_now\":") + std::to_string(weso->iterations.load()) + "}"); - // #endregion if (stop_signal) return Proof(); vdf_original vdfo_proof; uint64 checkpoint = (done_iterations + iters) - (done_iterations + iters) % 100; - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H17", - "vdf.h:ProveTwoWeso:depth2_before_checkpoint_get", - "Depth-2 loading checkpoint form", - std::string("{\"checkpoint\":") + std::to_string(checkpoint) + "}"); - // #endregion form y = weso->GetFormCopy(checkpoint); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H17", - "vdf.h:ProveTwoWeso:depth2_after_checkpoint_get", - "Depth-2 loaded checkpoint form", - "{}"); - // #endregion repeated_square_original(vdfo_proof, y, D, L, 0, (done_iterations + iters) % 100, NULL); Segment sg( @@ -553,23 +372,7 @@ Proof ProveTwoWeso(integer& D, form x, uint64_t iters, uint64_t done_iterations, /*y=*/y ); TwoWesolowskiProver prover(sg, D, weso, stop_signal); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H17", - "vdf.h:ProveTwoWeso:depth2_before_generate", - "Depth-2 prover GenerateProof start", - "{}"); - // #endregion prover.GenerateProof(); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H17", - "vdf.h:ProveTwoWeso:depth2_after_generate", - "Depth-2 prover GenerateProof finished", - "{}"); - // #endregion if (stop_signal) return Proof(); @@ -601,42 +404,10 @@ Proof ProveTwoWeso(integer& D, form x, uint64_t iters, uint64_t done_iterations, ); TwoWesolowskiProver prover(sg, D, weso, stop_signal); prover.start(); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H17", - "vdf.h:ProveTwoWeso:before_recursive_call", - "Calling recursive ProveTwoWeso", - std::string("{\"next_depth\":") + std::to_string(depth + 1) + - ",\"iterations2\":" + std::to_string(iterations2) + "}"); - // #endregion Proof proof2 = ProveTwoWeso(D, y1, iterations2, done_iterations + iterations1, weso, depth + 1, stop_signal); - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H17", - "vdf.h:ProveTwoWeso:after_recursive_call", - "Returned from recursive ProveTwoWeso", - "{}"); - // #endregion - - int wait_polls = 0; + while (!stop_signal && !prover.IsFinished()) { - if ((wait_polls % 50) == 0) { - // #region agent log - CallbackAgentDebugLog( - "post-fix", - "H52", - "vdf.h:ProveTwoWeso:wait_for_top_prover", - "Waiting for top-level prover completion", - std::string("{\"depth\":") + std::to_string(depth) + - ",\"done_iterations\":" + std::to_string(done_iterations) + - ",\"iterations_now\":" + std::to_string(weso->iterations.load()) + - ",\"wait_polls\":" + std::to_string(wait_polls) + "}"); - // #endregion - } std::this_thread::sleep_for (std::chrono::milliseconds(100)); - wait_polls++; } if (stop_signal) return Proof(); From 34223d3cef85bfac3ac370956e1624feb72af2d4 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Tue, 10 Feb 2026 22:26:56 -0800 Subject: [PATCH 30/78] address cursor review issues --- .github/workflows/test.yaml | 4 ++-- src/vdf.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index d6005c70..3f3c635b 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -174,9 +174,9 @@ jobs: if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } if ($dllPaths.Count -gt 0) { $env:PATH = ($dllPaths -join ';') + ';' + $env:PATH } - function Invoke-TestExe([string]$name, [string[]]$args = @()) { + function Invoke-TestExe([string]$name, [string[]]$testArgs = @()) { Write-Host "Running $name" - & ".\$name.exe" @args + & ".\$name.exe" @testArgs $exitCode = $LASTEXITCODE if ($exitCode -ne 0) { Write-Host "$name exit code: $exitCode" diff --git a/src/vdf.h b/src/vdf.h index d0f5af47..d7c1b8aa 100644 --- a/src/vdf.h +++ b/src/vdf.h @@ -131,7 +131,6 @@ static inline void repeated_square_nudupl( fallback_reducer.emplace(); } for (uint64_t i = 0; i < iterations; i++) { - const uint64_t current_iter = base + i + 1; nudupl_form(f, f, D, L); // Reduce only when `a` grows beyond a small limb threshold. Reducing every iteration From ba2c55c07090fc3107d6c4129707e0c2f6a2036d Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Tue, 10 Feb 2026 22:47:11 -0800 Subject: [PATCH 31/78] everything on windows should take the asm path --- .github/workflows/test.yaml | 19 ++++++++++++++++++- src/CMakeLists.txt | 23 ----------------------- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 3f3c635b..f70a17b5 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -120,10 +120,25 @@ jobs: "-DBUILD_VDF_CLIENT=ON", "-DBUILD_VDF_BENCH=ON", "-DBUILD_VDF_TESTS=ON", - "-DBUILD_HW_TOOLS=OFF" + "-DBUILD_HW_TOOLS=OFF", + "-DENABLE_GNU_ASM=ON" ) & cmake @cmakeArgs + $gnuAsmEnabled = (& cmake -N -L build | Select-String '^ENABLE_GNU_ASM:BOOL=ON$') + if (-not $gnuAsmEnabled) { + throw "ENABLE_GNU_ASM is not ON on Windows CI build" + } cmake --build build --target vdf_client vdf_bench 1weso_test 2weso_test prover_test + $asmFiles = @( + "build/asm_compiled.s", + "build/avx2_asm_compiled.s", + "build/avx512_asm_compiled.s" + ) + foreach ($asmFile in $asmFiles) { + if (-not (Test-Path $asmFile)) { + throw "Expected generated asm output not found: $asmFile" + } + } - name: Run vdf tests (optimized) if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') @@ -186,6 +201,8 @@ jobs: } Write-Host "Running 1weso_test" Invoke-TestExe "1weso_test" @("1000") + Write-Host "Running 2weso_test (smoke)" + Invoke-TestExe "2weso_test" @("100") Write-Host "Running 2weso_test" Invoke-TestExe "2weso_test" @("1000") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 982b620e..2b2f9f5a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -217,13 +217,6 @@ function(vdf_add_boost_includes target_name) endif() endfunction() -function(vdf_add_windows_asm_linker_flags target_name) - if(WIN32 AND ENABLE_GNU_ASM) - # chiavdf asm uses absolute 32-bit relocations on Windows - target_link_options(${target_name} PRIVATE "LINKER:/LARGEADDRESSAWARE:NO") - endif() -endfunction() - function(vdf_add_windows_clang_opts target_name) if(WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang") if(MSVC) @@ -257,7 +250,6 @@ if(BUILD_VDF_CLIENT) endif() vdf_add_boost_includes(vdf_client) target_link_libraries(vdf_client PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) - vdf_add_windows_asm_linker_flags(vdf_client) vdf_add_windows_clang_opts(vdf_client) endif() @@ -268,7 +260,6 @@ if(BUILD_VDF_BENCH) target_sources(vdf_bench PRIVATE ${VDF_COMMON_SOURCES} ${VDF_ASM_SOURCES}) target_compile_definitions(vdf_bench PRIVATE ${VDF_COMMON_DEFINITIONS}) target_link_libraries(vdf_bench PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) - vdf_add_windows_asm_linker_flags(vdf_bench) vdf_add_windows_clang_opts(vdf_bench) endif() @@ -278,12 +269,8 @@ if(BUILD_VDF_TESTS) ) target_sources(1weso_test PRIVATE ${VDF_COMMON_SOURCES} ${VDF_ASM_SOURCES}) target_compile_definitions(1weso_test PRIVATE ${VDF_COMMON_DEFINITIONS}) - if(WIN32) - target_compile_definitions(1weso_test PRIVATE CHIA_DISABLE_ASM) - endif() vdf_add_boost_includes(1weso_test) target_link_libraries(1weso_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) - vdf_add_windows_asm_linker_flags(1weso_test) vdf_add_windows_clang_opts(1weso_test) add_executable(2weso_test @@ -291,14 +278,8 @@ if(BUILD_VDF_TESTS) ) target_sources(2weso_test PRIVATE ${VDF_COMMON_SOURCES} ${VDF_ASM_SOURCES}) target_compile_definitions(2weso_test PRIVATE ${VDF_COMMON_DEFINITIONS}) - if(WIN32) - target_compile_definitions(2weso_test PRIVATE CHIA_DISABLE_ASM) - endif() vdf_add_boost_includes(2weso_test) target_link_libraries(2weso_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) - # Intentionally do not force /LARGEADDRESSAWARE:NO for 2weso_test. - # This target is built with CHIA_DISABLE_ASM on Windows, and we want to - # isolate crashes correlated with the linker flag. vdf_add_windows_clang_opts(2weso_test) add_executable(prover_test @@ -306,12 +287,8 @@ if(BUILD_VDF_TESTS) ) target_sources(prover_test PRIVATE ${VDF_COMMON_SOURCES} ${VDF_ASM_SOURCES}) target_compile_definitions(prover_test PRIVATE ${VDF_COMMON_DEFINITIONS}) - if(WIN32) - target_compile_definitions(prover_test PRIVATE CHIA_DISABLE_ASM) - endif() vdf_add_boost_includes(prover_test) target_link_libraries(prover_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) - vdf_add_windows_asm_linker_flags(prover_test) vdf_add_windows_clang_opts(prover_test) endif() From e5db303fd1c7ac87a31daf564cfd0a1bc634060c Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Tue, 10 Feb 2026 22:58:24 -0800 Subject: [PATCH 32/78] something about the windows asm path is broken --- src/1weso_test.cpp | 45 +++++++++++++++++++++++++++++++++++++++- src/vdf.h | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/1weso_test.cpp b/src/1weso_test.cpp index 48329ce2..ce848511 100644 --- a/src/1weso_test.cpp +++ b/src/1weso_test.cpp @@ -26,7 +26,17 @@ int main(int argc, char const* argv[]) try assert(is_vdf_test); //assertions should be disabled in VDF_MODE==0 init_gmp(); debug_mode = true; - if(hasAVX2()) + const bool has_avx2 = hasAVX2(); + // #region agent log + agent_debug_log_ndjson( + "H1", + "src/1weso_test.cpp:main:init", + "initialized_1weso_test", + std::string("{\"iter_multiplier\":") + std::to_string(iter_multiplier) + + ",\"has_avx2\":" + std::to_string(has_avx2 ? 1 : 0) + "}" + ); + // #endregion + if(has_avx2) { gcd_base_bits=63; gcd_128_max_iter=2; @@ -49,10 +59,43 @@ int main(int argc, char const* argv[]) try uint64_t iter = iter_multiplier; OneWesolowskiCallback weso(D, f, iter); FastStorage* fast_storage = nullptr; + // #region agent log + agent_debug_log_ndjson( + "H3", + "src/1weso_test.cpp:main:before_worker", + "starting_worker_thread", + std::string("{\"iter\":") + std::to_string(iter) + "}" + ); + // #endregion std::thread vdf_worker(repeated_square, iter, f, D, L, &weso, fast_storage, std::ref(stopped)); + // #region agent log + agent_debug_log_ndjson( + "H3", + "src/1weso_test.cpp:main:before_prove", + "calling_prove_one_wesolowski", + std::string("{\"iter\":") + std::to_string(iter) + "}" + ); + // #endregion Proof const proof = ProveOneWesolowski(iter, D, f, &weso, stopped); + // #region agent log + agent_debug_log_ndjson( + "H4", + "src/1weso_test.cpp:main:after_prove", + "prove_one_wesolowski_returned", + std::string("{\"proof_y_size\":") + std::to_string(proof.y.size()) + + ",\"proof_proof_size\":" + std::to_string(proof.proof.size()) + "}" + ); + // #endregion stopped = true; vdf_worker.join(); + // #region agent log + agent_debug_log_ndjson( + "H5", + "src/1weso_test.cpp:main:after_join", + "worker_joined_about_to_verify", + std::string("{\"iter\":") + std::to_string(iter) + "}" + ); + // #endregion bool is_valid; form x_init = form::generator(D); diff --git a/src/vdf.h b/src/vdf.h index d7c1b8aa..5364c008 100644 --- a/src/vdf.h +++ b/src/vdf.h @@ -48,6 +48,32 @@ #endif #include #include +#include +#include + +static inline void agent_debug_log_ndjson( + const char* hypothesis_id, + const char* location, + const char* message, + const std::string& data_json, + const char* run_id = "pre-fix" +) { + const long long ts_ms = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch() + ).count(); + std::ofstream out("/Users/hoffmang/src/chiavdf/.cursor/debug.log", std::ios::app); + if (!out.good()) { + return; + } + out << "{\"id\":\"log_" << ts_ms << "_" << hypothesis_id + << "\",\"timestamp\":" << ts_ms + << ",\"runId\":\"" << run_id + << "\",\"hypothesisId\":\"" << hypothesis_id + << "\",\"location\":\"" << location + << "\",\"message\":\"" << message + << "\",\"data\":" << data_json + << "}\n"; +} #include #include @@ -166,6 +192,7 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege uint64_t num_iterations = 0; uint64_t last_checkpoint = 0; + bool agent_logged_fast_path = false; while (!stopped) { uint64 c_checkpoint_interval=checkpoint_interval; @@ -197,7 +224,31 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege // x86/x64: use the phased pipeline. square_state_type square_state; square_state.pairindex = 0; + if (!agent_logged_fast_path) { + // #region agent log + agent_debug_log_ndjson( + "H2", + "src/vdf.h:repeated_square:fast_before", + "about_to_call_repeated_square_fast", + std::string("{\"num_iterations\":") + std::to_string(num_iterations) + + ",\"batch_size\":" + std::to_string(batch_size) + + ",\"iterations_arg\":" + std::to_string(iterations) + "}" + ); + // #endregion + } actual_iterations = repeated_square_fast(square_state, f, D, L, num_iterations, batch_size, weso); + if (!agent_logged_fast_path) { + // #region agent log + agent_debug_log_ndjson( + "H2", + "src/vdf.h:repeated_square:fast_after", + "returned_from_repeated_square_fast", + std::string("{\"actual_iterations\":") + std::to_string(actual_iterations) + + ",\"batch_size\":" + std::to_string(batch_size) + "}" + ); + // #endregion + agent_logged_fast_path = true; + } #else // Non-x86: use the C++ NUDUPL path (faster and lower maintenance than the phased pipeline). integer& D_nc = const_cast(D); From f9b2efa2f25b65bb2b656da1f870bb50861c75b7 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Tue, 10 Feb 2026 23:07:09 -0800 Subject: [PATCH 33/78] and we are off again searching for the asm issue --- src/1weso_test.cpp | 17 +++++++++++++++++ src/vdf.h | 9 +++++++++ 2 files changed, 26 insertions(+) diff --git a/src/1weso_test.cpp b/src/1weso_test.cpp index ce848511..01df943d 100644 --- a/src/1weso_test.cpp +++ b/src/1weso_test.cpp @@ -28,6 +28,10 @@ int main(int argc, char const* argv[]) try debug_mode = true; const bool has_avx2 = hasAVX2(); // #region agent log + std::cerr << "AGENTDBG H1 init iter_multiplier=" << iter_multiplier + << " has_avx2=" << (has_avx2 ? 1 : 0) << "\n"; + // #endregion + // #region agent log agent_debug_log_ndjson( "H1", "src/1weso_test.cpp:main:init", @@ -60,6 +64,9 @@ int main(int argc, char const* argv[]) try OneWesolowskiCallback weso(D, f, iter); FastStorage* fast_storage = nullptr; // #region agent log + std::cerr << "AGENTDBG H3 before_worker iter=" << iter << "\n"; + // #endregion + // #region agent log agent_debug_log_ndjson( "H3", "src/1weso_test.cpp:main:before_worker", @@ -69,6 +76,9 @@ int main(int argc, char const* argv[]) try // #endregion std::thread vdf_worker(repeated_square, iter, f, D, L, &weso, fast_storage, std::ref(stopped)); // #region agent log + std::cerr << "AGENTDBG H3 before_prove iter=" << iter << "\n"; + // #endregion + // #region agent log agent_debug_log_ndjson( "H3", "src/1weso_test.cpp:main:before_prove", @@ -78,6 +88,10 @@ int main(int argc, char const* argv[]) try // #endregion Proof const proof = ProveOneWesolowski(iter, D, f, &weso, stopped); // #region agent log + std::cerr << "AGENTDBG H4 after_prove proof_y_size=" << proof.y.size() + << " proof_proof_size=" << proof.proof.size() << "\n"; + // #endregion + // #region agent log agent_debug_log_ndjson( "H4", "src/1weso_test.cpp:main:after_prove", @@ -89,6 +103,9 @@ int main(int argc, char const* argv[]) try stopped = true; vdf_worker.join(); // #region agent log + std::cerr << "AGENTDBG H5 after_join iter=" << iter << "\n"; + // #endregion + // #region agent log agent_debug_log_ndjson( "H5", "src/1weso_test.cpp:main:after_join", diff --git a/src/vdf.h b/src/vdf.h index 5364c008..29001310 100644 --- a/src/vdf.h +++ b/src/vdf.h @@ -225,6 +225,11 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege square_state_type square_state; square_state.pairindex = 0; if (!agent_logged_fast_path) { + // #region agent log + std::cerr << "AGENTDBG H2 fast_before num_iterations=" << num_iterations + << " batch_size=" << batch_size + << " iterations_arg=" << iterations << "\n"; + // #endregion // #region agent log agent_debug_log_ndjson( "H2", @@ -238,6 +243,10 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege } actual_iterations = repeated_square_fast(square_state, f, D, L, num_iterations, batch_size, weso); if (!agent_logged_fast_path) { + // #region agent log + std::cerr << "AGENTDBG H2 fast_after actual_iterations=" << actual_iterations + << " batch_size=" << batch_size << "\n"; + // #endregion // #region agent log agent_debug_log_ndjson( "H2", From 14bf67007048640f601c7141906aaee8949f5149 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Tue, 10 Feb 2026 23:13:20 -0800 Subject: [PATCH 34/78] cache all the things and chase the asm issue --- .github/workflows/test.yaml | 27 +++++++++++++++++++++++++-- src/vdf.h | 16 ++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index f70a17b5..e975c25c 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -72,11 +72,26 @@ jobs: cd src make ${{ matrix.config }} CPPFLAGS="-I${BOOST_INCLUDE} ${CPPFLAGS:-}" -f Makefile.vdf-client + - name: Cache Boost on Windows + if: startsWith(matrix.os, 'windows') + id: cache-boost + uses: actions/cache@v4 + with: + path: C:\local\boost_* + key: windows-boost-msvc-14.3-v1 + - name: Install LLVM and Ninja on Windows if: startsWith(matrix.os, 'windows') shell: pwsh + env: + BOOST_CACHE_HIT: ${{ steps.cache-boost.outputs.cache-hit }} run: | - choco install llvm ninja boost-msvc-14.3 -y + choco install llvm ninja -y + if ("$env:BOOST_CACHE_HIT" -ne "true") { + choco install boost-msvc-14.3 -y + } else { + Write-Host "Boost cache hit, skipping boost-msvc-14.3 install" + } "C:\Program Files\LLVM\bin" | Out-File -Append -FilePath $env:GITHUB_PATH "CHIA_ENABLE_AVX512_IFMA=0" | Out-File -Append -FilePath $env:GITHUB_ENV $boostDir = Get-ChildItem "C:\local" -Directory -Filter "boost_*" | Select-Object -First 1 @@ -85,8 +100,16 @@ jobs: } "BOOST_INCLUDE_DIR=$($boostDir.FullName)" | Out-File -Append -FilePath $env:GITHUB_ENV - - name: Checkout mpir for Windows + - name: Cache mpir checkout on Windows if: startsWith(matrix.os, 'windows') + id: cache-mpir + uses: actions/cache@v4 + with: + path: mpir_gc_x64 + key: windows-mpir-gc-x64-v1 + + - name: Checkout mpir for Windows + if: startsWith(matrix.os, 'windows') && steps.cache-mpir.outputs.cache-hit != 'true' uses: actions/checkout@v6 with: repository: Chia-Network/mpir_gc_x64 diff --git a/src/vdf.h b/src/vdf.h index 29001310..922ea2d9 100644 --- a/src/vdf.h +++ b/src/vdf.h @@ -294,7 +294,17 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege //the fast algorithm terminated prematurely for whatever reason. f is still valid //it might terminate prematurely again (e.g. gcd quotient too large), so will do one iteration of the slow algorithm //this will also reduce f if the fast algorithm terminated because it was too big + // #region agent log + std::cerr << "AGENTDBG H6 fallback_before_slow num_iterations=" << num_iterations + << " actual_iterations=" << actual_iterations + << " batch_size=" << batch_size << "\n"; + // #endregion repeated_square_original(*weso->vdfo, f, D, L, num_iterations+actual_iterations, 1, weso); + // #region agent log + std::cerr << "AGENTDBG H6 fallback_after_slow num_iterations=" << num_iterations + << " actual_iterations=" << actual_iterations + << " batch_size=" << batch_size << "\n"; + // #endregion #ifdef VDF_TEST ++num_iterations_slow; @@ -308,6 +318,12 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege } num_iterations+=actual_iterations; + // #region agent log + if (num_iterations == actual_iterations) { + std::cerr << "AGENTDBG H7 first_loop_after_accumulate num_iterations=" << num_iterations + << " last_checkpoint=" << last_checkpoint << "\n"; + } + // #endregion if (num_iterations >= last_checkpoint) { weso->iterations = num_iterations; From 52e9b563006966da1bff2995d93cd7f9d4b32cc2 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Tue, 10 Feb 2026 23:24:33 -0800 Subject: [PATCH 35/78] look closer at the ubuntu vs windows asm changes --- src/vdf.h | 13 +++++++++---- src/vdf_fast.h | 26 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/vdf.h b/src/vdf.h index 922ea2d9..6f45d12a 100644 --- a/src/vdf.h +++ b/src/vdf.h @@ -224,12 +224,14 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege // x86/x64: use the phased pipeline. square_state_type square_state; square_state.pairindex = 0; - if (!agent_logged_fast_path) { + if (num_iterations < 32) { // #region agent log - std::cerr << "AGENTDBG H2 fast_before num_iterations=" << num_iterations + std::cerr << "AGENTDBG H9 fast_before_iter num_iterations=" << num_iterations << " batch_size=" << batch_size << " iterations_arg=" << iterations << "\n"; // #endregion + } + if (!agent_logged_fast_path) { // #region agent log agent_debug_log_ndjson( "H2", @@ -242,11 +244,14 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege // #endregion } actual_iterations = repeated_square_fast(square_state, f, D, L, num_iterations, batch_size, weso); - if (!agent_logged_fast_path) { + if (num_iterations < 32) { // #region agent log - std::cerr << "AGENTDBG H2 fast_after actual_iterations=" << actual_iterations + std::cerr << "AGENTDBG H9 fast_after_iter num_iterations=" << num_iterations + << " actual_iterations=" << actual_iterations << " batch_size=" << batch_size << "\n"; // #endregion + } + if (!agent_logged_fast_path) { // #region agent log agent_debug_log_ndjson( "H2", diff --git a/src/vdf_fast.h b/src/vdf_fast.h index 571a0d04..61b42eb8 100644 --- a/src/vdf_fast.h +++ b/src/vdf_fast.h @@ -1092,12 +1092,24 @@ uint64 repeated_square_fast_single_thread(square_state_type &square_state, form& for (int phase=0;phase Date: Tue, 10 Feb 2026 23:33:52 -0800 Subject: [PATCH 36/78] Consolidate Windows asm investigation commits 1-17. Squash iterative CI and asm-path probing changes into one reviewable checkpoint before the final CI fix commit. Co-authored-by: Cursor --- .github/workflows/test.yaml | 35 ++++++-- src/1weso_test.cpp | 59 ++++++++++++++ src/CMakeLists.txt | 2 +- src/asm_base.h | 59 +++++++++++++- src/asm_gcd_unsigned.h | 2 +- src/threading.h | 83 ++++++++++++++++++- src/vdf.h | 19 +++++ src/vdf_fast.h | 156 ++++++++++++++++++++++++++++++++++++ 8 files changed, 404 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index e975c25c..10b4b678 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -75,7 +75,7 @@ jobs: - name: Cache Boost on Windows if: startsWith(matrix.os, 'windows') id: cache-boost - uses: actions/cache@v4 + uses: actions/cache/restore@v4 with: path: C:\local\boost_* key: windows-boost-msvc-14.3-v1 @@ -86,20 +86,43 @@ jobs: env: BOOST_CACHE_HIT: ${{ steps.cache-boost.outputs.cache-hit }} run: | - choco install llvm ninja -y - if ("$env:BOOST_CACHE_HIT" -ne "true") { - choco install boost-msvc-14.3 -y + $llvmBin = "C:\Program Files\LLVM\bin\clang-cl.exe" + $ninjaBin = "C:\ProgramData\chocolatey\bin\ninja.exe" + if (-not (Test-Path $llvmBin) -or -not (Test-Path $ninjaBin)) { + Write-Host "LLVM/Ninja not found, installing via choco" + choco install llvm ninja -y + } else { + Write-Host "LLVM and Ninja already present, skipping choco install" + } + + $boostDir = Get-ChildItem "C:\local" -Directory -Filter "boost_*" -ErrorAction SilentlyContinue | Select-Object -First 1 + if (-not $boostDir) { + if ("$env:BOOST_CACHE_HIT" -ne "true") { + Write-Host "Boost cache miss and boost not found, installing boost-msvc-14.3" + choco install boost-msvc-14.3 -y + } else { + Write-Host "Boost cache reported hit but boost directory missing; reinstalling boost-msvc-14.3" + choco install boost-msvc-14.3 -y + } + $boostDir = Get-ChildItem "C:\local" -Directory -Filter "boost_*" -ErrorAction SilentlyContinue | Select-Object -First 1 } else { - Write-Host "Boost cache hit, skipping boost-msvc-14.3 install" + Write-Host "Boost already present at $($boostDir.FullName), skipping choco install" } + "C:\Program Files\LLVM\bin" | Out-File -Append -FilePath $env:GITHUB_PATH "CHIA_ENABLE_AVX512_IFMA=0" | Out-File -Append -FilePath $env:GITHUB_ENV - $boostDir = Get-ChildItem "C:\local" -Directory -Filter "boost_*" | Select-Object -First 1 if (-not $boostDir) { throw "Boost install not found under C:\local" } "BOOST_INCLUDE_DIR=$($boostDir.FullName)" | Out-File -Append -FilePath $env:GITHUB_ENV + - name: Save Boost cache on Windows + if: startsWith(matrix.os, 'windows') && steps.cache-boost.outputs.cache-hit != 'true' + uses: actions/cache/save@v4 + with: + path: C:\local\boost_* + key: ${{ steps.cache-boost.outputs.cache-primary-key }} + - name: Cache mpir checkout on Windows if: startsWith(matrix.os, 'windows') id: cache-mpir diff --git a/src/1weso_test.cpp b/src/1weso_test.cpp index 01df943d..509eadfb 100644 --- a/src/1weso_test.cpp +++ b/src/1weso_test.cpp @@ -4,6 +4,9 @@ #include #include +#ifdef _WIN32 +#include +#endif int segments = 7; int thread_count = 3; @@ -15,6 +18,55 @@ Proof CreateProof(ProverManager& pm, uint64_t iteration) { int gcd_base_bits=50; int gcd_128_max_iter=3; +#ifdef _WIN32 +#ifdef GENERATE_ASM_TRACKING_DATA +static LONG WINAPI dump_asm_tracking_on_crash(EXCEPTION_POINTERS*) { + std::cerr << "AGENTDBG H16 seh_unhandled_exception\n"; + for (int i = 0; i < num_asm_tracking_data; ++i) { + if (!asm_tracking_data_comments[i]) { + continue; + } + if (asm_tracking_data[i] == 0) { + continue; + } + std::cerr << "AGENTDBG H16 asm_track idx=" << i + << " count=" << asm_tracking_data[i] + << " label=" << asm_tracking_data_comments[i] << "\n"; + } + return EXCEPTION_EXECUTE_HANDLER; +} +#endif + +static LONG CALLBACK agent_vectored_exception_logger(EXCEPTION_POINTERS* info) { + if (info == nullptr || info->ExceptionRecord == nullptr) { + return EXCEPTION_CONTINUE_SEARCH; + } + const auto* rec = info->ExceptionRecord; + const void* addr = rec->ExceptionAddress; + const uintptr_t crash_ip = reinterpret_cast(addr); + const uintptr_t avx2_gcd_unsigned_ip = reinterpret_cast(&asm_code::asm_avx2_func_gcd_unsigned); + const uintptr_t cel_gcd_unsigned_ip = reinterpret_cast(&asm_code::asm_cel_func_gcd_unsigned); + const uintptr_t avx2_gcd_128_ip = reinterpret_cast(&asm_code::asm_avx2_func_gcd_128); + const uintptr_t cel_gcd_128_ip = reinterpret_cast(&asm_code::asm_cel_func_gcd_128); + const uintptr_t module_base = reinterpret_cast(GetModuleHandleA(nullptr)); + std::cerr << "AGENTDBG H24 veh_exception" + << " code=0x" << std::hex << static_cast(rec->ExceptionCode) << std::dec + << " flags=0x" << std::hex << static_cast(rec->ExceptionFlags) << std::dec + << " thread_id=" << GetCurrentThreadId() + << " address=" << addr + << " params=" << rec->NumberParameters + << " module_base=0x" << std::hex << module_base + << " ip_rva=0x" << (crash_ip - module_base) + << " d_avx2_gcd_unsigned=0x" << (crash_ip - avx2_gcd_unsigned_ip) + << " d_cel_gcd_unsigned=0x" << (crash_ip - cel_gcd_unsigned_ip) + << " d_avx2_gcd_128=0x" << (crash_ip - avx2_gcd_128_ip) + << " d_cel_gcd_128=0x" << (crash_ip - cel_gcd_128_ip) + << std::dec + << "\n"; + return EXCEPTION_CONTINUE_SEARCH; +} +#endif + int main(int argc, char const* argv[]) try { // allow setting the multiplier for the number of iterations to test on the @@ -25,6 +77,13 @@ int main(int argc, char const* argv[]) try assert(is_vdf_test); //assertions should be disabled in VDF_MODE==0 init_gmp(); +#ifdef _WIN32 + void* agent_veh_handle = AddVectoredExceptionHandler(1, agent_vectored_exception_logger); + (void)agent_veh_handle; +#ifdef GENERATE_ASM_TRACKING_DATA + SetUnhandledExceptionFilter(dump_asm_tracking_on_crash); +#endif +#endif debug_mode = true; const bool has_avx2 = hasAVX2(); // #region agent log diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2b2f9f5a..f5a11220 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -83,7 +83,7 @@ endif() # CMake 3.14+ include(FetchContent) -set(VDF_COMMON_DEFINITIONS VDF_MODE=0 FAST_MACHINE=1) +set(VDF_COMMON_DEFINITIONS VDF_MODE=0 FAST_MACHINE=1 GENERATE_ASM_TRACKING_DATA=1) set(VDF_COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/refcode/lzcnt.c ) diff --git a/src/asm_base.h b/src/asm_base.h index 9621fd78..bac55d19 100644 --- a/src/asm_base.h +++ b/src/asm_base.h @@ -1,3 +1,5 @@ +#include + #ifdef GENERATE_ASM_TRACKING_DATA const bool generate_asm_tracking_data=true; #else @@ -6,6 +8,27 @@ namespace asm_code { +inline void agent_debug_log_ndjson_file(const char* hypothesis_id, const char* location, const char* message, const string& data_json) { + // #region agent log + std::ofstream agent_debug_log("/Users/hoffmang/src/chiavdf/.cursor/debug.log", std::ios::app); + if (!agent_debug_log.is_open()) { + return; + } + const auto timestamp_ms = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch() + ).count(); + agent_debug_log + << "{\"id\":\"log_" << timestamp_ms << "_" << hypothesis_id + << "\",\"timestamp\":" << timestamp_ms + << ",\"runId\":\"windows-link-debug\"" + << ",\"hypothesisId\":\"" << hypothesis_id << "\"" + << ",\"location\":\"" << location << "\"" + << ",\"message\":\"" << message << "\"" + << ",\"data\":" << data_json + << "}\n"; + // #endregion +} + string track_asm(string comment, string jump_to = "") { if (!generate_asm_tracking_data) { @@ -53,7 +76,26 @@ string track_asm(string comment, string jump_to = "") { } string comment_label=m.alloc_label(); + // #region agent log + agent_debug_log_ndjson_file( + "H2", + "src/asm_base.h:track_asm:alloc_label", + "allocated_comment_label_for_tracking", + std::string("{\"comment_label\":\"") + comment_label + + "\",\"asmprefix\":\"" + asmprefix + + "\",\"starts_with_prefix\":" + + ((comment_label.rfind("_" + asmprefix, 0) == 0) ? "1" : "0") + "}" + ); + // #endregion #if defined(CHIA_WINDOWS) + // #region agent log + agent_debug_log_ndjson_file( + "H3", + "src/asm_base.h:track_asm:section_select", + "emitting_comment_string_in_windows_rdata", + "{\"selected_section\":\".section .rdata,\\\"dr\\\"\"}" + ); + // #endregion APPEND_M(str( ".section .rdata,\"dr\"" )); #elif defined(CHIAOSX) APPEND_M(str( ".text " )); @@ -84,7 +126,22 @@ string track_asm(string comment, string jump_to = "") { APPEND_M(str( "LEA RAX, [RAX+1]" )); APPEND_M(str( "MOV [asm_tracking_data+#], RAX", to_hex(8*(id-1)) )); #if defined(CHIAOSX) || defined(CHIA_WINDOWS) - APPEND_M(str( "LEA RAX, [RIP+comment_label] " )); + // #region agent log + agent_debug_log_ndjson_file( + "H4", + "src/asm_base.h:track_asm:comment_pointer_emit", + "about_to_emit_comment_label_pointer", + std::string("{\"comment_label\":\"") + comment_label + + "\",\"is_windows\":" + +#ifdef CHIA_WINDOWS + "1" +#else + "0" +#endif + + ",\"operand_literal\":\"RIP+comment_label\"}" + ); + // #endregion + APPEND_M(str( "LEA RAX, [RIP+#] ", comment_label )); #else APPEND_M(str( "MOV RAX, OFFSET FLAT:#", comment_label )); #endif diff --git a/src/asm_gcd_unsigned.h b/src/asm_gcd_unsigned.h index 63979e7e..ddbfc728 100644 --- a/src/asm_gcd_unsigned.h +++ b/src/asm_gcd_unsigned.h @@ -443,7 +443,7 @@ void gcd_unsigned( string jump_table_label=m.alloc_label(); #ifdef CHIA_WINDOWS - APPEND_M(str( ".section .rdata,\"dr\"" )); + APPEND_M(str( ".text" )); #elif defined(CHIAOSX) APPEND_M(str( ".text " )); #else diff --git a/src/threading.h b/src/threading.h index 3ba24596..ee1d19b7 100644 --- a/src/threading.h +++ b/src/threading.h @@ -3,6 +3,9 @@ #include "alloc.hpp" #include +#ifdef _WIN32 +#include +#endif //mp_limb_t is an unsigned integer static_assert(sizeof(mp_limb_t)==8, ""); @@ -791,9 +794,85 @@ template bool gcd_unsigned( assert((uint64(data.out_uv_addr)&63)==0); //should be cache line aligned } - int error_code=hasAVX2()? - asm_code::asm_avx2_func_gcd_unsigned(&data): + // #region agent log + if (a_limbs >= 3) { + std::cerr << "AGENTDBG H14 gcd_enter" + << " is_slave=" << (c_thread_state.is_slave ? 1 : 0) + << " counter_start=" << c_thread_state.counter_start + << " counter_start_delta=" << counter_start_delta + << " a_limbs=" << a_limbs + << " b_limbs=" << b_limbs + << " a_end_index=" << data.a_end_index + << " a_ptr_mod64=" << (uint64(data.a) & 63) + << " b_ptr_mod64=" << (uint64(data.b) & 63) + << " a2_ptr_mod64=" << (uint64(data.a_2) & 63) + << " b2_ptr_mod64=" << (uint64(data.b_2) & 63) + << " th_ptr_mod64=" << (uint64(data.threshold) & 63) + << " th_ptr_mod32=" << (uint64(data.threshold) & 31) + << " out_uv_counter_ptr_mod64=" << (uint64(data.out_uv_counter_addr) & 63) + << " out_uv_ptr_mod64=" << (uint64(data.out_uv_addr) & 63) + << " a_eq_a2=" << (data.a == data.a_2 ? 1 : 0) + << " b_eq_b2=" << (data.b == data.b_2 ? 1 : 0) + << " has_avx2=" << (hasAVX2() ? 1 : 0) + << "\n"; + } + // #endregion + + bool force_cel_gcd=false; +#ifdef CHIA_WINDOWS + { + const char* force_cel_gcd_env = getenv("CHIA_DEBUG_FORCE_CEL_GCD"); + force_cel_gcd = (force_cel_gcd_env && force_cel_gcd_env[0] != 0 && force_cel_gcd_env[0] != '0'); + } +#endif + const bool use_avx2_gcd = hasAVX2() && !force_cel_gcd; + // #region agent log + if (a_limbs >= 3) { + std::cerr << "AGENTDBG H15 gcd_impl_select" + << " is_slave=" << (c_thread_state.is_slave ? 1 : 0) + << " use_avx2=" << (use_avx2_gcd ? 1 : 0) + << " force_cel=" << (force_cel_gcd ? 1 : 0) + << " a0=" << data.a[0] + << " b0=" << data.b[0] + << " th0=" << data.threshold[0] + << "\n"; + } + // #endregion + int error_code = 0; +#ifdef CHIA_WINDOWS + unsigned long agent_seh_code = 0; + __try { + error_code = use_avx2_gcd ? + asm_code::asm_avx2_func_gcd_unsigned(&data) : + asm_code::asm_cel_func_gcd_unsigned(&data); + } __except ((agent_seh_code = GetExceptionCode()), EXCEPTION_EXECUTE_HANDLER) { + // #region agent log + std::cerr << "AGENTDBG H22 seh_in_gcd_asm" + << " is_slave=" << (c_thread_state.is_slave ? 1 : 0) + << " use_avx2=" << (use_avx2_gcd ? 1 : 0) + << " code=0x" << std::hex << agent_seh_code << std::dec + << " a0=" << data.a[0] + << " b0=" << data.b[0] + << " a_end_index=" << data.a_end_index + << "\n"; + // #endregion + error_code = -1; + } +#else + error_code = use_avx2_gcd ? + asm_code::asm_avx2_func_gcd_unsigned(&data) : asm_code::asm_cel_func_gcd_unsigned(&data); +#endif + + // #region agent log + if (a_limbs >= 3) { + std::cerr << "AGENTDBG H14 gcd_after_asm" + << " is_slave=" << (c_thread_state.is_slave ? 1 : 0) + << " error_code=" << error_code + << " iter=" << data.iter + << "\n"; + } + // #endregion if (error_code!=0) { c_thread_state.raise_error(); diff --git a/src/vdf.h b/src/vdf.h index 6f45d12a..055de6fc 100644 --- a/src/vdf.h +++ b/src/vdf.h @@ -224,6 +224,16 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege // x86/x64: use the phased pipeline. square_state_type square_state; square_state.pairindex = 0; + static std::atomic agent_active_fast_calls{0}; + const int agent_active_fast_now = agent_active_fast_calls.fetch_add(1, std::memory_order_relaxed) + 1; + // #region agent log + if (num_iterations < 32 || agent_active_fast_now > 1) { + std::cerr << "AGENTDBG H21 fast_call_enter pairindex=" << square_state.pairindex + << " num_iterations=" << num_iterations + << " batch_size=" << batch_size + << " active_fast_calls=" << agent_active_fast_now << "\n"; + } + // #endregion if (num_iterations < 32) { // #region agent log std::cerr << "AGENTDBG H9 fast_before_iter num_iterations=" << num_iterations @@ -244,6 +254,15 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege // #endregion } actual_iterations = repeated_square_fast(square_state, f, D, L, num_iterations, batch_size, weso); + const int agent_active_fast_left = agent_active_fast_calls.fetch_sub(1, std::memory_order_relaxed) - 1; + // #region agent log + if (num_iterations < 32 || agent_active_fast_now > 1 || agent_active_fast_left > 0) { + std::cerr << "AGENTDBG H21 fast_call_exit pairindex=" << square_state.pairindex + << " num_iterations=" << num_iterations + << " actual_iterations=" << actual_iterations + << " active_fast_calls_left=" << agent_active_fast_left << "\n"; + } + // #endregion if (num_iterations < 32) { // #region agent log std::cerr << "AGENTDBG H9 fast_after_iter num_iterations=" << num_iterations diff --git a/src/vdf_fast.h b/src/vdf_fast.h index 61b42eb8..b5f24935 100644 --- a/src/vdf_fast.h +++ b/src/vdf_fast.h @@ -185,6 +185,14 @@ struct square_state_type { // bool phase_0_master() { + // #region agent log + if (phase_start.num_valid_iterations == 0) { + std::cerr << "AGENTDBG H13 p0_master_enter a_bits=" << phase_start.a().num_bits() + << " b_bits=" << phase_start.b().num_bits() + << " a_sgn=" << phase_start.a().sgn() + << " b_higher=" << (phase_start.b_higher_magnitude_than_a ? 1 : 0) << "\n"; + } + // #endregion { TRACK_CYCLES //100 if (!c_thread_state.fence(counter_start_phase_0)) { @@ -222,6 +230,14 @@ struct square_state_type { ab_valid=(a.num_bits()<=max_bits_ab && b.num_bits()<=max_bits_ab && a.sgn()>=0); } if (!ab_valid) { + // #region agent log + if (phase_start.num_valid_iterations == 0) { + std::cerr << "AGENTDBG H13 p0_master_ab_invalid a_bits=" << a.num_bits() + << " b_bits=" << b.num_bits() + << " max_bits_ab=" << max_bits_ab + << " a_sgn=" << a.sgn() << "\n"; + } + // #endregion return false; } @@ -233,6 +249,12 @@ struct square_state_type { a_high_enough=(a.num_limbs()>L.num_limbs()); } if (!a_high_enough) { + // #region agent log + if (phase_start.num_valid_iterations == 0) { + std::cerr << "AGENTDBG H13 p0_master_a_low a_limbs=" << a.num_limbs() + << " L_limbs=" << L.num_limbs() << "\n"; + } + // #endregion return false; } @@ -246,16 +268,39 @@ struct square_state_type { { TRACK_CYCLES //16070 (critical path 1) + // #region agent log + if (phase_start.num_valid_iterations == 0) { + std::cerr << "AGENTDBG H13 p0_master_before_gcd\n"; + } + // #endregion if (!gcd_unsigned(counter_start_phase_0, gcd_1_0, gcd_zero)) { TRACK_CYCLES_ABORT + // #region agent log + if (phase_start.num_valid_iterations == 0) { + std::cerr << "AGENTDBG H13 p0_master_gcd_false\n"; + } + // #endregion return false; } + // #region agent log + if (phase_start.num_valid_iterations == 0) { + std::cerr << "AGENTDBG H13 p0_master_after_gcd\n"; + } + // #endregion } return true; } bool phase_0_slave() { + // #region agent log + if (phase_start.num_valid_iterations == 0) { + std::cerr << "AGENTDBG H13 p0_slave_enter a_bits=" << phase_start.a().num_bits() + << " b_bits=" << phase_start.b().num_bits() + << " a_sgn=" << phase_start.a().sgn() + << " b_higher=" << (phase_start.b_higher_magnitude_than_a ? 1 : 0) << "\n"; + } + // #endregion { TRACK_CYCLES //1698 (doesn't matter) if (!c_thread_state.fence(counter_start_phase_0)) { @@ -306,7 +351,17 @@ struct square_state_type { if (!validate_c) { TRACK_CYCLES //747 + // #region agent log + if (phase_start.num_valid_iterations == 0) { + std::cerr << "AGENTDBG H13 p0_slave_before_divide_exact\n"; + } + // #endregion c.set_divide_exact(b_b_D, a_4); + // #region agent log + if (phase_start.num_valid_iterations == 0) { + std::cerr << "AGENTDBG H13 p0_slave_after_divide_exact\n"; + } + // #endregion } else { TRACK_CYCLES //1309; latency is hidden by gcd being slow c.set_divide_floor(b_b_D, a_4, c_remainder); @@ -1002,24 +1057,79 @@ void repeated_square_fast_work(square_state_type &square_state, bool is_slave, u c_thread_state.reset(); c_thread_state.is_slave=is_slave; c_thread_state.pairindex=square_state.pairindex; + // #region agent log + if (base < 32) { + std::cerr << "AGENTDBG H12 work_enter base=" << base + << " is_slave=" << (is_slave ? 1 : 0) + << " iterations=" << iterations << "\n"; + } + // #endregion bool has_error=false; + int agent_phase=-1; + uint64 agent_iter=0; +#ifdef CHIA_WINDOWS + unsigned long agent_work_seh_code = 0; + __try { +#endif for (uint64 iter=0;iter Date: Wed, 11 Feb 2026 19:20:29 -0800 Subject: [PATCH 37/78] Fix Windows asm CI and align optimized test coverage (#304) * Instrument Windows asm failures and collect runtime evidence. Add targeted Windows probes and disassembly checks to localize crash offsets and failing asm paths. Co-authored-by: Cursor * Fix Windows asm addressing to be ASLR-safe. Convert global and table references to RIP-relative forms for Windows asm generation paths. Co-authored-by: Cursor * Stabilize Windows gcd_unsigned dispatch control flow. Correct dispatch indexing and use explicit compare/branch selection to avoid executing table data. Co-authored-by: Cursor * Fix Windows CI probe exit-code handling. Ensure PowerShell helpers compare integer process exit codes so successful probes do not fail the workflow. Co-authored-by: Cursor * Remove temporary Windows debug instrumentation. Drop crash-debug hooks and probes after validation, including the final vdf_fast cleanup. Co-authored-by: Cursor * Align Windows optimized test coverage with other runners. Run the full optimized test set in the Windows PowerShell test step by removing ad-hoc iteration args and adding prover_test with fast mode. Co-authored-by: Cursor * Clean up leftover no-op debug checks in fast path and tighten macOS-only branch selection in gcd_unsigned. This removes empty instrumentation cleanup blocks and keeps the dispatch path logic aligned with platform-specific behavior. Co-authored-by: Cursor * Restore Windows jump-table dispatch path in gcd_unsigned. This reverts an accidental macOS-only condition change from the prior cleanup commit that caused 1weso_test to crash on Windows CI. Co-authored-by: Cursor --------- Co-authored-by: Cursor --- .github/workflows/test.yaml | 11 +- src/1weso_test.cpp | 118 ---------------- src/asm_base.h | 67 +-------- src/asm_gcd_base_continued_fractions.h | 2 +- src/asm_gcd_base_divide_table.h | 2 +- src/asm_gcd_unsigned.h | 13 +- src/threading.h | 78 +---------- src/vdf.h | 99 ------------- src/vdf_fast.h | 183 ------------------------- 9 files changed, 25 insertions(+), 548 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 10b4b678..b8e18756 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -228,8 +228,6 @@ jobs: if: matrix.config == 'optimized=1' && startsWith(matrix.os, 'windows') shell: pwsh run: | - Write-Host "CI commit (HEAD): $env:GITHUB_SHA" - git rev-parse --short HEAD cd build $dllPaths = @() if ($env:MPIR_ROOT -and (Test-Path "$env:MPIR_ROOT\bin")) { $dllPaths += "$env:MPIR_ROOT\bin" } @@ -246,11 +244,12 @@ jobs: return $exitCode } Write-Host "Running 1weso_test" - Invoke-TestExe "1weso_test" @("1000") - Write-Host "Running 2weso_test (smoke)" - Invoke-TestExe "2weso_test" @("100") + Invoke-TestExe "1weso_test" Write-Host "Running 2weso_test" - Invoke-TestExe "2weso_test" @("1000") + Invoke-TestExe "2weso_test" + Write-Host "Running prover_test" + $env:CHIAVDF_PROVER_TEST_FAST = "1" + Invoke-TestExe "prover_test" - name: Benchmark vdf_bench square (Ubuntu/Mac) if: matrix.config == 'optimized=1' && !startsWith(matrix.os, 'windows') diff --git a/src/1weso_test.cpp b/src/1weso_test.cpp index 509eadfb..e922f3f0 100644 --- a/src/1weso_test.cpp +++ b/src/1weso_test.cpp @@ -4,9 +4,6 @@ #include #include -#ifdef _WIN32 -#include -#endif int segments = 7; int thread_count = 3; @@ -18,55 +15,6 @@ Proof CreateProof(ProverManager& pm, uint64_t iteration) { int gcd_base_bits=50; int gcd_128_max_iter=3; -#ifdef _WIN32 -#ifdef GENERATE_ASM_TRACKING_DATA -static LONG WINAPI dump_asm_tracking_on_crash(EXCEPTION_POINTERS*) { - std::cerr << "AGENTDBG H16 seh_unhandled_exception\n"; - for (int i = 0; i < num_asm_tracking_data; ++i) { - if (!asm_tracking_data_comments[i]) { - continue; - } - if (asm_tracking_data[i] == 0) { - continue; - } - std::cerr << "AGENTDBG H16 asm_track idx=" << i - << " count=" << asm_tracking_data[i] - << " label=" << asm_tracking_data_comments[i] << "\n"; - } - return EXCEPTION_EXECUTE_HANDLER; -} -#endif - -static LONG CALLBACK agent_vectored_exception_logger(EXCEPTION_POINTERS* info) { - if (info == nullptr || info->ExceptionRecord == nullptr) { - return EXCEPTION_CONTINUE_SEARCH; - } - const auto* rec = info->ExceptionRecord; - const void* addr = rec->ExceptionAddress; - const uintptr_t crash_ip = reinterpret_cast(addr); - const uintptr_t avx2_gcd_unsigned_ip = reinterpret_cast(&asm_code::asm_avx2_func_gcd_unsigned); - const uintptr_t cel_gcd_unsigned_ip = reinterpret_cast(&asm_code::asm_cel_func_gcd_unsigned); - const uintptr_t avx2_gcd_128_ip = reinterpret_cast(&asm_code::asm_avx2_func_gcd_128); - const uintptr_t cel_gcd_128_ip = reinterpret_cast(&asm_code::asm_cel_func_gcd_128); - const uintptr_t module_base = reinterpret_cast(GetModuleHandleA(nullptr)); - std::cerr << "AGENTDBG H24 veh_exception" - << " code=0x" << std::hex << static_cast(rec->ExceptionCode) << std::dec - << " flags=0x" << std::hex << static_cast(rec->ExceptionFlags) << std::dec - << " thread_id=" << GetCurrentThreadId() - << " address=" << addr - << " params=" << rec->NumberParameters - << " module_base=0x" << std::hex << module_base - << " ip_rva=0x" << (crash_ip - module_base) - << " d_avx2_gcd_unsigned=0x" << (crash_ip - avx2_gcd_unsigned_ip) - << " d_cel_gcd_unsigned=0x" << (crash_ip - cel_gcd_unsigned_ip) - << " d_avx2_gcd_128=0x" << (crash_ip - avx2_gcd_128_ip) - << " d_cel_gcd_128=0x" << (crash_ip - cel_gcd_128_ip) - << std::dec - << "\n"; - return EXCEPTION_CONTINUE_SEARCH; -} -#endif - int main(int argc, char const* argv[]) try { // allow setting the multiplier for the number of iterations to test on the @@ -77,28 +25,8 @@ int main(int argc, char const* argv[]) try assert(is_vdf_test); //assertions should be disabled in VDF_MODE==0 init_gmp(); -#ifdef _WIN32 - void* agent_veh_handle = AddVectoredExceptionHandler(1, agent_vectored_exception_logger); - (void)agent_veh_handle; -#ifdef GENERATE_ASM_TRACKING_DATA - SetUnhandledExceptionFilter(dump_asm_tracking_on_crash); -#endif -#endif debug_mode = true; const bool has_avx2 = hasAVX2(); - // #region agent log - std::cerr << "AGENTDBG H1 init iter_multiplier=" << iter_multiplier - << " has_avx2=" << (has_avx2 ? 1 : 0) << "\n"; - // #endregion - // #region agent log - agent_debug_log_ndjson( - "H1", - "src/1weso_test.cpp:main:init", - "initialized_1weso_test", - std::string("{\"iter_multiplier\":") + std::to_string(iter_multiplier) + - ",\"has_avx2\":" + std::to_string(has_avx2 ? 1 : 0) + "}" - ); - // #endregion if(has_avx2) { gcd_base_bits=63; @@ -122,56 +50,10 @@ int main(int argc, char const* argv[]) try uint64_t iter = iter_multiplier; OneWesolowskiCallback weso(D, f, iter); FastStorage* fast_storage = nullptr; - // #region agent log - std::cerr << "AGENTDBG H3 before_worker iter=" << iter << "\n"; - // #endregion - // #region agent log - agent_debug_log_ndjson( - "H3", - "src/1weso_test.cpp:main:before_worker", - "starting_worker_thread", - std::string("{\"iter\":") + std::to_string(iter) + "}" - ); - // #endregion std::thread vdf_worker(repeated_square, iter, f, D, L, &weso, fast_storage, std::ref(stopped)); - // #region agent log - std::cerr << "AGENTDBG H3 before_prove iter=" << iter << "\n"; - // #endregion - // #region agent log - agent_debug_log_ndjson( - "H3", - "src/1weso_test.cpp:main:before_prove", - "calling_prove_one_wesolowski", - std::string("{\"iter\":") + std::to_string(iter) + "}" - ); - // #endregion Proof const proof = ProveOneWesolowski(iter, D, f, &weso, stopped); - // #region agent log - std::cerr << "AGENTDBG H4 after_prove proof_y_size=" << proof.y.size() - << " proof_proof_size=" << proof.proof.size() << "\n"; - // #endregion - // #region agent log - agent_debug_log_ndjson( - "H4", - "src/1weso_test.cpp:main:after_prove", - "prove_one_wesolowski_returned", - std::string("{\"proof_y_size\":") + std::to_string(proof.y.size()) + - ",\"proof_proof_size\":" + std::to_string(proof.proof.size()) + "}" - ); - // #endregion stopped = true; vdf_worker.join(); - // #region agent log - std::cerr << "AGENTDBG H5 after_join iter=" << iter << "\n"; - // #endregion - // #region agent log - agent_debug_log_ndjson( - "H5", - "src/1weso_test.cpp:main:after_join", - "worker_joined_about_to_verify", - std::string("{\"iter\":") + std::to_string(iter) + "}" - ); - // #endregion bool is_valid; form x_init = form::generator(D); diff --git a/src/asm_base.h b/src/asm_base.h index bac55d19..a1257925 100644 --- a/src/asm_base.h +++ b/src/asm_base.h @@ -1,5 +1,3 @@ -#include - #ifdef GENERATE_ASM_TRACKING_DATA const bool generate_asm_tracking_data=true; #else @@ -8,27 +6,6 @@ namespace asm_code { -inline void agent_debug_log_ndjson_file(const char* hypothesis_id, const char* location, const char* message, const string& data_json) { - // #region agent log - std::ofstream agent_debug_log("/Users/hoffmang/src/chiavdf/.cursor/debug.log", std::ios::app); - if (!agent_debug_log.is_open()) { - return; - } - const auto timestamp_ms = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch() - ).count(); - agent_debug_log - << "{\"id\":\"log_" << timestamp_ms << "_" << hypothesis_id - << "\",\"timestamp\":" << timestamp_ms - << ",\"runId\":\"windows-link-debug\"" - << ",\"hypothesisId\":\"" << hypothesis_id << "\"" - << ",\"location\":\"" << location << "\"" - << ",\"message\":\"" << message << "\"" - << ",\"data\":" << data_json - << "}\n"; - // #endregion -} - string track_asm(string comment, string jump_to = "") { if (!generate_asm_tracking_data) { @@ -76,26 +53,7 @@ string track_asm(string comment, string jump_to = "") { } string comment_label=m.alloc_label(); - // #region agent log - agent_debug_log_ndjson_file( - "H2", - "src/asm_base.h:track_asm:alloc_label", - "allocated_comment_label_for_tracking", - std::string("{\"comment_label\":\"") + comment_label + - "\",\"asmprefix\":\"" + asmprefix + - "\",\"starts_with_prefix\":" + - ((comment_label.rfind("_" + asmprefix, 0) == 0) ? "1" : "0") + "}" - ); - // #endregion #if defined(CHIA_WINDOWS) - // #region agent log - agent_debug_log_ndjson_file( - "H3", - "src/asm_base.h:track_asm:section_select", - "emitting_comment_string_in_windows_rdata", - "{\"selected_section\":\".section .rdata,\\\"dr\\\"\"}" - ); - // #endregion APPEND_M(str( ".section .rdata,\"dr\"" )); #elif defined(CHIAOSX) APPEND_M(str( ".text " )); @@ -121,32 +79,17 @@ string track_asm(string comment, string jump_to = "") { assert(!enable_threads); //this code isn't atomic - APPEND_M(str( "MOV [track_asm_rax], RAX" )); - APPEND_M(str( "MOV RAX, [asm_tracking_data+#]", to_hex(8*(id-1)) )); + APPEND_M(str( "MOV [RIP+track_asm_rax], RAX" )); + APPEND_M(str( "MOV RAX, [RIP+asm_tracking_data+#]", to_hex(8*(id-1)) )); APPEND_M(str( "LEA RAX, [RAX+1]" )); - APPEND_M(str( "MOV [asm_tracking_data+#], RAX", to_hex(8*(id-1)) )); + APPEND_M(str( "MOV [RIP+asm_tracking_data+#], RAX", to_hex(8*(id-1)) )); #if defined(CHIAOSX) || defined(CHIA_WINDOWS) - // #region agent log - agent_debug_log_ndjson_file( - "H4", - "src/asm_base.h:track_asm:comment_pointer_emit", - "about_to_emit_comment_label_pointer", - std::string("{\"comment_label\":\"") + comment_label + - "\",\"is_windows\":" + -#ifdef CHIA_WINDOWS - "1" -#else - "0" -#endif - + ",\"operand_literal\":\"RIP+comment_label\"}" - ); - // #endregion APPEND_M(str( "LEA RAX, [RIP+#] ", comment_label )); #else APPEND_M(str( "MOV RAX, OFFSET FLAT:#", comment_label )); #endif - APPEND_M(str( "MOV [asm_tracking_data_comments+#], RAX", to_hex(8*(id-1)) )); - APPEND_M(str( "MOV RAX, [track_asm_rax]" )); + APPEND_M(str( "MOV [RIP+asm_tracking_data_comments+#], RAX", to_hex(8*(id-1)) )); + APPEND_M(str( "MOV RAX, [RIP+track_asm_rax]" )); if (!jump_to.empty()) { APPEND_M(str( "JMP #", jump_to )); diff --git a/src/asm_gcd_base_continued_fractions.h b/src/asm_gcd_base_continued_fractions.h index 935bb2c3..6b201aa0 100644 --- a/src/asm_gcd_base_continued_fractions.h +++ b/src/asm_gcd_base_continued_fractions.h @@ -187,7 +187,7 @@ void gcd_base_continued_fraction( //m_0: column 0 //m_1: column 1 -#ifdef CHIAOSX +#if defined(CHIAOSX) || defined(CHIA_WINDOWS) APPEND_M(str( "LEA RSI,[RIP+")+asmprefix+str("gcd_base_table]")); APPEND_M(str( "MOVAPD `m_0, [`q_scalar+RSI]" )); APPEND_M(str( "MOVAPD `m_1, [16+`q_scalar+RSI]" )); diff --git a/src/asm_gcd_base_divide_table.h b/src/asm_gcd_base_divide_table.h index 57ccfaf8..8a7e2dfa 100644 --- a/src/asm_gcd_base_divide_table.h +++ b/src/asm_gcd_base_divide_table.h @@ -59,7 +59,7 @@ void divide_table(reg_alloc regs, reg_scalar a, reg_scalar b, reg_scalar q, reg_ APPEND_M(str( "#:", b_shift_label )); APPEND_M(str( "SARX RAX, `b, `q" )); // b_approx = b>>b_shift -#ifdef CHIAOSX +#if defined(CHIAOSX) || defined(CHIA_WINDOWS) APPEND_M(str( "LEA RCX, [RIP+divide_table]" )); // b_approx_inverse = divide_table[b_approx] APPEND_M(str( "MOV RAX, [RCX+RAX*8]")); #else diff --git a/src/asm_gcd_unsigned.h b/src/asm_gcd_unsigned.h index ddbfc728..a005f11f 100644 --- a/src/asm_gcd_unsigned.h +++ b/src/asm_gcd_unsigned.h @@ -452,7 +452,7 @@ void gcd_unsigned( APPEND_M(str( ".balign 8" )); APPEND_M(str( "#:", jump_table_label )); -#ifdef CHIAOSX +#if defined(CHIAOSX) || defined(CHIA_WINDOWS) APPEND_M(str( ".text" )); APPEND_M(str( "MOV `tmp, `spill_a_end_index" )); @@ -482,8 +482,19 @@ void gcd_unsigned( } APPEND_M(str( ".text" )); + string bad_end_index_label = track_asm( "gcd_unsigned invalid a_end_index", m.alloc_error_label() ); APPEND_M(str( "MOV `tmp, `spill_a_end_index" )); + APPEND_M(str( "SUB `tmp, 1" )); + APPEND_M(str( "JC #", bad_end_index_label )); + APPEND_M(str( "CMP `tmp, #", to_hex(int_size-1) )); + APPEND_M(str( "JA #", bad_end_index_label )); +#ifdef CHIA_WINDOWS + reg_scalar table_addr=regs.bind_scalar(m, "table_addr"); + APPEND_M(str( "LEA `table_addr, [RIP+#]", jump_table_label )); + APPEND_M(str( "JMP QWORD PTR [`table_addr+`tmp*8]" )); +#else APPEND_M(str( "JMP QWORD PTR [#+`tmp*8]", jump_table_label )); +#endif #endif } for (int size=4;size<=int_size;size+=4) { diff --git a/src/threading.h b/src/threading.h index ee1d19b7..08c4869c 100644 --- a/src/threading.h +++ b/src/threading.h @@ -794,85 +794,9 @@ template bool gcd_unsigned( assert((uint64(data.out_uv_addr)&63)==0); //should be cache line aligned } - // #region agent log - if (a_limbs >= 3) { - std::cerr << "AGENTDBG H14 gcd_enter" - << " is_slave=" << (c_thread_state.is_slave ? 1 : 0) - << " counter_start=" << c_thread_state.counter_start - << " counter_start_delta=" << counter_start_delta - << " a_limbs=" << a_limbs - << " b_limbs=" << b_limbs - << " a_end_index=" << data.a_end_index - << " a_ptr_mod64=" << (uint64(data.a) & 63) - << " b_ptr_mod64=" << (uint64(data.b) & 63) - << " a2_ptr_mod64=" << (uint64(data.a_2) & 63) - << " b2_ptr_mod64=" << (uint64(data.b_2) & 63) - << " th_ptr_mod64=" << (uint64(data.threshold) & 63) - << " th_ptr_mod32=" << (uint64(data.threshold) & 31) - << " out_uv_counter_ptr_mod64=" << (uint64(data.out_uv_counter_addr) & 63) - << " out_uv_ptr_mod64=" << (uint64(data.out_uv_addr) & 63) - << " a_eq_a2=" << (data.a == data.a_2 ? 1 : 0) - << " b_eq_b2=" << (data.b == data.b_2 ? 1 : 0) - << " has_avx2=" << (hasAVX2() ? 1 : 0) - << "\n"; - } - // #endregion - - bool force_cel_gcd=false; -#ifdef CHIA_WINDOWS - { - const char* force_cel_gcd_env = getenv("CHIA_DEBUG_FORCE_CEL_GCD"); - force_cel_gcd = (force_cel_gcd_env && force_cel_gcd_env[0] != 0 && force_cel_gcd_env[0] != '0'); - } -#endif - const bool use_avx2_gcd = hasAVX2() && !force_cel_gcd; - // #region agent log - if (a_limbs >= 3) { - std::cerr << "AGENTDBG H15 gcd_impl_select" - << " is_slave=" << (c_thread_state.is_slave ? 1 : 0) - << " use_avx2=" << (use_avx2_gcd ? 1 : 0) - << " force_cel=" << (force_cel_gcd ? 1 : 0) - << " a0=" << data.a[0] - << " b0=" << data.b[0] - << " th0=" << data.threshold[0] - << "\n"; - } - // #endregion - int error_code = 0; -#ifdef CHIA_WINDOWS - unsigned long agent_seh_code = 0; - __try { - error_code = use_avx2_gcd ? - asm_code::asm_avx2_func_gcd_unsigned(&data) : - asm_code::asm_cel_func_gcd_unsigned(&data); - } __except ((agent_seh_code = GetExceptionCode()), EXCEPTION_EXECUTE_HANDLER) { - // #region agent log - std::cerr << "AGENTDBG H22 seh_in_gcd_asm" - << " is_slave=" << (c_thread_state.is_slave ? 1 : 0) - << " use_avx2=" << (use_avx2_gcd ? 1 : 0) - << " code=0x" << std::hex << agent_seh_code << std::dec - << " a0=" << data.a[0] - << " b0=" << data.b[0] - << " a_end_index=" << data.a_end_index - << "\n"; - // #endregion - error_code = -1; - } -#else - error_code = use_avx2_gcd ? + int error_code = hasAVX2() ? asm_code::asm_avx2_func_gcd_unsigned(&data) : asm_code::asm_cel_func_gcd_unsigned(&data); -#endif - - // #region agent log - if (a_limbs >= 3) { - std::cerr << "AGENTDBG H14 gcd_after_asm" - << " is_slave=" << (c_thread_state.is_slave ? 1 : 0) - << " error_code=" << error_code - << " iter=" << data.iter - << "\n"; - } - // #endregion if (error_code!=0) { c_thread_state.raise_error(); diff --git a/src/vdf.h b/src/vdf.h index 055de6fc..38bcafca 100644 --- a/src/vdf.h +++ b/src/vdf.h @@ -49,31 +49,6 @@ #include #include #include -#include - -static inline void agent_debug_log_ndjson( - const char* hypothesis_id, - const char* location, - const char* message, - const std::string& data_json, - const char* run_id = "pre-fix" -) { - const long long ts_ms = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch() - ).count(); - std::ofstream out("/Users/hoffmang/src/chiavdf/.cursor/debug.log", std::ios::app); - if (!out.good()) { - return; - } - out << "{\"id\":\"log_" << ts_ms << "_" << hypothesis_id - << "\",\"timestamp\":" << ts_ms - << ",\"runId\":\"" << run_id - << "\",\"hypothesisId\":\"" << hypothesis_id - << "\",\"location\":\"" << location - << "\",\"message\":\"" << message - << "\",\"data\":" << data_json - << "}\n"; -} #include #include @@ -192,7 +167,6 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege uint64_t num_iterations = 0; uint64_t last_checkpoint = 0; - bool agent_logged_fast_path = false; while (!stopped) { uint64 c_checkpoint_interval=checkpoint_interval; @@ -224,64 +198,7 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege // x86/x64: use the phased pipeline. square_state_type square_state; square_state.pairindex = 0; - static std::atomic agent_active_fast_calls{0}; - const int agent_active_fast_now = agent_active_fast_calls.fetch_add(1, std::memory_order_relaxed) + 1; - // #region agent log - if (num_iterations < 32 || agent_active_fast_now > 1) { - std::cerr << "AGENTDBG H21 fast_call_enter pairindex=" << square_state.pairindex - << " num_iterations=" << num_iterations - << " batch_size=" << batch_size - << " active_fast_calls=" << agent_active_fast_now << "\n"; - } - // #endregion - if (num_iterations < 32) { - // #region agent log - std::cerr << "AGENTDBG H9 fast_before_iter num_iterations=" << num_iterations - << " batch_size=" << batch_size - << " iterations_arg=" << iterations << "\n"; - // #endregion - } - if (!agent_logged_fast_path) { - // #region agent log - agent_debug_log_ndjson( - "H2", - "src/vdf.h:repeated_square:fast_before", - "about_to_call_repeated_square_fast", - std::string("{\"num_iterations\":") + std::to_string(num_iterations) + - ",\"batch_size\":" + std::to_string(batch_size) + - ",\"iterations_arg\":" + std::to_string(iterations) + "}" - ); - // #endregion - } actual_iterations = repeated_square_fast(square_state, f, D, L, num_iterations, batch_size, weso); - const int agent_active_fast_left = agent_active_fast_calls.fetch_sub(1, std::memory_order_relaxed) - 1; - // #region agent log - if (num_iterations < 32 || agent_active_fast_now > 1 || agent_active_fast_left > 0) { - std::cerr << "AGENTDBG H21 fast_call_exit pairindex=" << square_state.pairindex - << " num_iterations=" << num_iterations - << " actual_iterations=" << actual_iterations - << " active_fast_calls_left=" << agent_active_fast_left << "\n"; - } - // #endregion - if (num_iterations < 32) { - // #region agent log - std::cerr << "AGENTDBG H9 fast_after_iter num_iterations=" << num_iterations - << " actual_iterations=" << actual_iterations - << " batch_size=" << batch_size << "\n"; - // #endregion - } - if (!agent_logged_fast_path) { - // #region agent log - agent_debug_log_ndjson( - "H2", - "src/vdf.h:repeated_square:fast_after", - "returned_from_repeated_square_fast", - std::string("{\"actual_iterations\":") + std::to_string(actual_iterations) + - ",\"batch_size\":" + std::to_string(batch_size) + "}" - ); - // #endregion - agent_logged_fast_path = true; - } #else // Non-x86: use the C++ NUDUPL path (faster and lower maintenance than the phased pipeline). integer& D_nc = const_cast(D); @@ -318,17 +235,7 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege //the fast algorithm terminated prematurely for whatever reason. f is still valid //it might terminate prematurely again (e.g. gcd quotient too large), so will do one iteration of the slow algorithm //this will also reduce f if the fast algorithm terminated because it was too big - // #region agent log - std::cerr << "AGENTDBG H6 fallback_before_slow num_iterations=" << num_iterations - << " actual_iterations=" << actual_iterations - << " batch_size=" << batch_size << "\n"; - // #endregion repeated_square_original(*weso->vdfo, f, D, L, num_iterations+actual_iterations, 1, weso); - // #region agent log - std::cerr << "AGENTDBG H6 fallback_after_slow num_iterations=" << num_iterations - << " actual_iterations=" << actual_iterations - << " batch_size=" << batch_size << "\n"; - // #endregion #ifdef VDF_TEST ++num_iterations_slow; @@ -342,12 +249,6 @@ void repeated_square(uint64_t iterations, form f, const integer& D, const intege } num_iterations+=actual_iterations; - // #region agent log - if (num_iterations == actual_iterations) { - std::cerr << "AGENTDBG H7 first_loop_after_accumulate num_iterations=" << num_iterations - << " last_checkpoint=" << last_checkpoint << "\n"; - } - // #endregion if (num_iterations >= last_checkpoint) { weso->iterations = num_iterations; diff --git a/src/vdf_fast.h b/src/vdf_fast.h index b5f24935..83728654 100644 --- a/src/vdf_fast.h +++ b/src/vdf_fast.h @@ -185,14 +185,6 @@ struct square_state_type { // bool phase_0_master() { - // #region agent log - if (phase_start.num_valid_iterations == 0) { - std::cerr << "AGENTDBG H13 p0_master_enter a_bits=" << phase_start.a().num_bits() - << " b_bits=" << phase_start.b().num_bits() - << " a_sgn=" << phase_start.a().sgn() - << " b_higher=" << (phase_start.b_higher_magnitude_than_a ? 1 : 0) << "\n"; - } - // #endregion { TRACK_CYCLES //100 if (!c_thread_state.fence(counter_start_phase_0)) { @@ -230,14 +222,6 @@ struct square_state_type { ab_valid=(a.num_bits()<=max_bits_ab && b.num_bits()<=max_bits_ab && a.sgn()>=0); } if (!ab_valid) { - // #region agent log - if (phase_start.num_valid_iterations == 0) { - std::cerr << "AGENTDBG H13 p0_master_ab_invalid a_bits=" << a.num_bits() - << " b_bits=" << b.num_bits() - << " max_bits_ab=" << max_bits_ab - << " a_sgn=" << a.sgn() << "\n"; - } - // #endregion return false; } @@ -249,12 +233,6 @@ struct square_state_type { a_high_enough=(a.num_limbs()>L.num_limbs()); } if (!a_high_enough) { - // #region agent log - if (phase_start.num_valid_iterations == 0) { - std::cerr << "AGENTDBG H13 p0_master_a_low a_limbs=" << a.num_limbs() - << " L_limbs=" << L.num_limbs() << "\n"; - } - // #endregion return false; } @@ -268,39 +246,16 @@ struct square_state_type { { TRACK_CYCLES //16070 (critical path 1) - // #region agent log - if (phase_start.num_valid_iterations == 0) { - std::cerr << "AGENTDBG H13 p0_master_before_gcd\n"; - } - // #endregion if (!gcd_unsigned(counter_start_phase_0, gcd_1_0, gcd_zero)) { TRACK_CYCLES_ABORT - // #region agent log - if (phase_start.num_valid_iterations == 0) { - std::cerr << "AGENTDBG H13 p0_master_gcd_false\n"; - } - // #endregion return false; } - // #region agent log - if (phase_start.num_valid_iterations == 0) { - std::cerr << "AGENTDBG H13 p0_master_after_gcd\n"; - } - // #endregion } return true; } bool phase_0_slave() { - // #region agent log - if (phase_start.num_valid_iterations == 0) { - std::cerr << "AGENTDBG H13 p0_slave_enter a_bits=" << phase_start.a().num_bits() - << " b_bits=" << phase_start.b().num_bits() - << " a_sgn=" << phase_start.a().sgn() - << " b_higher=" << (phase_start.b_higher_magnitude_than_a ? 1 : 0) << "\n"; - } - // #endregion { TRACK_CYCLES //1698 (doesn't matter) if (!c_thread_state.fence(counter_start_phase_0)) { @@ -351,17 +306,7 @@ struct square_state_type { if (!validate_c) { TRACK_CYCLES //747 - // #region agent log - if (phase_start.num_valid_iterations == 0) { - std::cerr << "AGENTDBG H13 p0_slave_before_divide_exact\n"; - } - // #endregion c.set_divide_exact(b_b_D, a_4); - // #region agent log - if (phase_start.num_valid_iterations == 0) { - std::cerr << "AGENTDBG H13 p0_slave_after_divide_exact\n"; - } - // #endregion } else { TRACK_CYCLES //1309; latency is hidden by gcd being slow c.set_divide_floor(b_b_D, a_4, c_remainder); @@ -1057,79 +1002,23 @@ void repeated_square_fast_work(square_state_type &square_state, bool is_slave, u c_thread_state.reset(); c_thread_state.is_slave=is_slave; c_thread_state.pairindex=square_state.pairindex; - // #region agent log - if (base < 32) { - std::cerr << "AGENTDBG H12 work_enter base=" << base - << " is_slave=" << (is_slave ? 1 : 0) - << " iterations=" << iterations << "\n"; - } - // #endregion bool has_error=false; - int agent_phase=-1; - uint64 agent_iter=0; - -#ifdef CHIA_WINDOWS - unsigned long agent_work_seh_code = 0; - __try { -#endif for (uint64 iter=0;iter Date: Wed, 11 Feb 2026 20:42:53 -0800 Subject: [PATCH 38/78] cleanup: finalize Windows asm follow-ups and include hygiene Tighten Windows asm/runtime plumbing and related docs/tests while removing stale duplicate include clutter from vdf headers. Co-authored-by: Cursor --- README.md | 9 +- src/asm_gcd_unsigned.h | 8 - src/asm_vm.h | 72 +++++--- src/uint128_t/uint128_t.cpp | 4 + src/vdf.h | 2 - src/vdf_base_integer.cpp | 342 ------------------------------------ 6 files changed, 59 insertions(+), 378 deletions(-) delete mode 100644 src/vdf_base_integer.cpp diff --git a/README.md b/README.md index b0d59fa5..7631e6e5 100644 --- a/README.md +++ b/README.md @@ -60,11 +60,12 @@ cmake -S src -B build \ cmake --build build --target vdf_client vdf_bench 1weso_test 2weso_test prover_test ``` -To build vdf_client set the environment variable BUILD_VDF_CLIENT to "Y". -`export BUILD_VDF_CLIENT=Y`. +For the legacy `setup.py` + `Makefile.vdf-client` flow (used by wheel hooks), +you can control native binary builds with environment variables: -Similarly, to build vdf_bench set the environment variable BUILD_VDF_BENCH to -"Y". `export BUILD_VDF_BENCH=Y`. +- `BUILD_VDF_CLIENT=Y` to include `vdf_client` (and related test binaries) +- `BUILD_VDF_BENCH=Y` to include `vdf_bench` +For direct CMake builds, use `-DBUILD_*` flags instead of these environment variables. AVX runtime flags: diff --git a/src/asm_gcd_unsigned.h b/src/asm_gcd_unsigned.h index a005f11f..d76eafec 100644 --- a/src/asm_gcd_unsigned.h +++ b/src/asm_gcd_unsigned.h @@ -484,17 +484,9 @@ void gcd_unsigned( string bad_end_index_label = track_asm( "gcd_unsigned invalid a_end_index", m.alloc_error_label() ); APPEND_M(str( "MOV `tmp, `spill_a_end_index" )); - APPEND_M(str( "SUB `tmp, 1" )); - APPEND_M(str( "JC #", bad_end_index_label )); APPEND_M(str( "CMP `tmp, #", to_hex(int_size-1) )); APPEND_M(str( "JA #", bad_end_index_label )); -#ifdef CHIA_WINDOWS - reg_scalar table_addr=regs.bind_scalar(m, "table_addr"); - APPEND_M(str( "LEA `table_addr, [RIP+#]", jump_table_label )); - APPEND_M(str( "JMP QWORD PTR [`table_addr+`tmp*8]" )); -#else APPEND_M(str( "JMP QWORD PTR [#+`tmp*8]", jump_table_label )); -#endif #endif } for (int size=4;size<=int_size;size+=4) { diff --git a/src/asm_vm.h b/src/asm_vm.h index aba80542..eb1cd2b9 100644 --- a/src/asm_vm.h +++ b/src/asm_vm.h @@ -119,7 +119,8 @@ struct asm_function { // Windows x64: reserve spill area + shadow space + xmm save area + align to 64. const int windows_saved_rsp_bytes = 8; const int windows_shadow_space_bytes = 0x20; - const int windows_xmm_save_bytes = 10 * 32; // YMM6-15 + const int windows_xmm_slot_bytes = enable_all_instructions ? 32 : 16; + const int windows_xmm_save_bytes = 10 * windows_xmm_slot_bytes; // XMM6-15 (or YMM6-15 for AVX codegen) const int windows_frame_bytes = windows_saved_rsp_bytes + spill_bytes + windows_shadow_space_bytes + windows_xmm_save_bytes; APPEND_M(str( "MOV RAX, RSP" )); @@ -129,16 +130,29 @@ struct asm_function { APPEND_M(str( "SUB RSP, 8" )); APPEND_M(str( "MOV [RSP], RAX" )); const int windows_xmm_save_base = windows_saved_rsp_bytes + spill_bytes + windows_shadow_space_bytes; - APPEND_M(str( "VMOVDQU [RSP+#], YMM6", to_hex(windows_xmm_save_base + 0 * 32) )); - APPEND_M(str( "VMOVDQU [RSP+#], YMM7", to_hex(windows_xmm_save_base + 1 * 32) )); - APPEND_M(str( "VMOVDQU [RSP+#], YMM8", to_hex(windows_xmm_save_base + 2 * 32) )); - APPEND_M(str( "VMOVDQU [RSP+#], YMM9", to_hex(windows_xmm_save_base + 3 * 32) )); - APPEND_M(str( "VMOVDQU [RSP+#], YMM10", to_hex(windows_xmm_save_base + 4 * 32) )); - APPEND_M(str( "VMOVDQU [RSP+#], YMM11", to_hex(windows_xmm_save_base + 5 * 32) )); - APPEND_M(str( "VMOVDQU [RSP+#], YMM12", to_hex(windows_xmm_save_base + 6 * 32) )); - APPEND_M(str( "VMOVDQU [RSP+#], YMM13", to_hex(windows_xmm_save_base + 7 * 32) )); - APPEND_M(str( "VMOVDQU [RSP+#], YMM14", to_hex(windows_xmm_save_base + 8 * 32) )); - APPEND_M(str( "VMOVDQU [RSP+#], YMM15", to_hex(windows_xmm_save_base + 9 * 32) )); + if (enable_all_instructions) { + APPEND_M(str( "VMOVDQU [RSP+#], YMM6", to_hex(windows_xmm_save_base + 0 * windows_xmm_slot_bytes) )); + APPEND_M(str( "VMOVDQU [RSP+#], YMM7", to_hex(windows_xmm_save_base + 1 * windows_xmm_slot_bytes) )); + APPEND_M(str( "VMOVDQU [RSP+#], YMM8", to_hex(windows_xmm_save_base + 2 * windows_xmm_slot_bytes) )); + APPEND_M(str( "VMOVDQU [RSP+#], YMM9", to_hex(windows_xmm_save_base + 3 * windows_xmm_slot_bytes) )); + APPEND_M(str( "VMOVDQU [RSP+#], YMM10", to_hex(windows_xmm_save_base + 4 * windows_xmm_slot_bytes) )); + APPEND_M(str( "VMOVDQU [RSP+#], YMM11", to_hex(windows_xmm_save_base + 5 * windows_xmm_slot_bytes) )); + APPEND_M(str( "VMOVDQU [RSP+#], YMM12", to_hex(windows_xmm_save_base + 6 * windows_xmm_slot_bytes) )); + APPEND_M(str( "VMOVDQU [RSP+#], YMM13", to_hex(windows_xmm_save_base + 7 * windows_xmm_slot_bytes) )); + APPEND_M(str( "VMOVDQU [RSP+#], YMM14", to_hex(windows_xmm_save_base + 8 * windows_xmm_slot_bytes) )); + APPEND_M(str( "VMOVDQU [RSP+#], YMM15", to_hex(windows_xmm_save_base + 9 * windows_xmm_slot_bytes) )); + } else { + APPEND_M(str( "MOVDQU [RSP+#], XMM6", to_hex(windows_xmm_save_base + 0 * windows_xmm_slot_bytes) )); + APPEND_M(str( "MOVDQU [RSP+#], XMM7", to_hex(windows_xmm_save_base + 1 * windows_xmm_slot_bytes) )); + APPEND_M(str( "MOVDQU [RSP+#], XMM8", to_hex(windows_xmm_save_base + 2 * windows_xmm_slot_bytes) )); + APPEND_M(str( "MOVDQU [RSP+#], XMM9", to_hex(windows_xmm_save_base + 3 * windows_xmm_slot_bytes) )); + APPEND_M(str( "MOVDQU [RSP+#], XMM10", to_hex(windows_xmm_save_base + 4 * windows_xmm_slot_bytes) )); + APPEND_M(str( "MOVDQU [RSP+#], XMM11", to_hex(windows_xmm_save_base + 5 * windows_xmm_slot_bytes) )); + APPEND_M(str( "MOVDQU [RSP+#], XMM12", to_hex(windows_xmm_save_base + 6 * windows_xmm_slot_bytes) )); + APPEND_M(str( "MOVDQU [RSP+#], XMM13", to_hex(windows_xmm_save_base + 7 * windows_xmm_slot_bytes) )); + APPEND_M(str( "MOVDQU [RSP+#], XMM14", to_hex(windows_xmm_save_base + 8 * windows_xmm_slot_bytes) )); + APPEND_M(str( "MOVDQU [RSP+#], XMM15", to_hex(windows_xmm_save_base + 9 * windows_xmm_slot_bytes) )); + } #else // RSP'=RSP&(~63) ; this makes it 64-aligned and can only reduce its value // RSP''=RSP'-64 ; still 64-aligned but now there is at least 64 bytes of unused stuff @@ -166,20 +180,34 @@ struct asm_function { //this takes 4 cycles including ret, if there is nothing else to do if (d_align_stack) { #ifdef CHIA_WINDOWS - // Windows ABI: restore YMM6–YMM15 from the stack area reserved during prologue. + // Windows ABI: restore XMM6-XMM15 (or YMM6-YMM15 for AVX codegen). const int windows_saved_rsp_bytes = 8; const int windows_shadow_space_bytes = 0x20; + const int windows_xmm_slot_bytes = enable_all_instructions ? 32 : 16; const int windows_xmm_save_base = windows_saved_rsp_bytes + spill_bytes + windows_shadow_space_bytes; - APPEND_M(str( "VMOVDQU YMM6, [RSP+#]", to_hex(windows_xmm_save_base + 0 * 32) )); - APPEND_M(str( "VMOVDQU YMM7, [RSP+#]", to_hex(windows_xmm_save_base + 1 * 32) )); - APPEND_M(str( "VMOVDQU YMM8, [RSP+#]", to_hex(windows_xmm_save_base + 2 * 32) )); - APPEND_M(str( "VMOVDQU YMM9, [RSP+#]", to_hex(windows_xmm_save_base + 3 * 32) )); - APPEND_M(str( "VMOVDQU YMM10, [RSP+#]", to_hex(windows_xmm_save_base + 4 * 32) )); - APPEND_M(str( "VMOVDQU YMM11, [RSP+#]", to_hex(windows_xmm_save_base + 5 * 32) )); - APPEND_M(str( "VMOVDQU YMM12, [RSP+#]", to_hex(windows_xmm_save_base + 6 * 32) )); - APPEND_M(str( "VMOVDQU YMM13, [RSP+#]", to_hex(windows_xmm_save_base + 7 * 32) )); - APPEND_M(str( "VMOVDQU YMM14, [RSP+#]", to_hex(windows_xmm_save_base + 8 * 32) )); - APPEND_M(str( "VMOVDQU YMM15, [RSP+#]", to_hex(windows_xmm_save_base + 9 * 32) )); + if (enable_all_instructions) { + APPEND_M(str( "VMOVDQU YMM6, [RSP+#]", to_hex(windows_xmm_save_base + 0 * windows_xmm_slot_bytes) )); + APPEND_M(str( "VMOVDQU YMM7, [RSP+#]", to_hex(windows_xmm_save_base + 1 * windows_xmm_slot_bytes) )); + APPEND_M(str( "VMOVDQU YMM8, [RSP+#]", to_hex(windows_xmm_save_base + 2 * windows_xmm_slot_bytes) )); + APPEND_M(str( "VMOVDQU YMM9, [RSP+#]", to_hex(windows_xmm_save_base + 3 * windows_xmm_slot_bytes) )); + APPEND_M(str( "VMOVDQU YMM10, [RSP+#]", to_hex(windows_xmm_save_base + 4 * windows_xmm_slot_bytes) )); + APPEND_M(str( "VMOVDQU YMM11, [RSP+#]", to_hex(windows_xmm_save_base + 5 * windows_xmm_slot_bytes) )); + APPEND_M(str( "VMOVDQU YMM12, [RSP+#]", to_hex(windows_xmm_save_base + 6 * windows_xmm_slot_bytes) )); + APPEND_M(str( "VMOVDQU YMM13, [RSP+#]", to_hex(windows_xmm_save_base + 7 * windows_xmm_slot_bytes) )); + APPEND_M(str( "VMOVDQU YMM14, [RSP+#]", to_hex(windows_xmm_save_base + 8 * windows_xmm_slot_bytes) )); + APPEND_M(str( "VMOVDQU YMM15, [RSP+#]", to_hex(windows_xmm_save_base + 9 * windows_xmm_slot_bytes) )); + } else { + APPEND_M(str( "MOVDQU XMM6, [RSP+#]", to_hex(windows_xmm_save_base + 0 * windows_xmm_slot_bytes) )); + APPEND_M(str( "MOVDQU XMM7, [RSP+#]", to_hex(windows_xmm_save_base + 1 * windows_xmm_slot_bytes) )); + APPEND_M(str( "MOVDQU XMM8, [RSP+#]", to_hex(windows_xmm_save_base + 2 * windows_xmm_slot_bytes) )); + APPEND_M(str( "MOVDQU XMM9, [RSP+#]", to_hex(windows_xmm_save_base + 3 * windows_xmm_slot_bytes) )); + APPEND_M(str( "MOVDQU XMM10, [RSP+#]", to_hex(windows_xmm_save_base + 4 * windows_xmm_slot_bytes) )); + APPEND_M(str( "MOVDQU XMM11, [RSP+#]", to_hex(windows_xmm_save_base + 5 * windows_xmm_slot_bytes) )); + APPEND_M(str( "MOVDQU XMM12, [RSP+#]", to_hex(windows_xmm_save_base + 6 * windows_xmm_slot_bytes) )); + APPEND_M(str( "MOVDQU XMM13, [RSP+#]", to_hex(windows_xmm_save_base + 7 * windows_xmm_slot_bytes) )); + APPEND_M(str( "MOVDQU XMM14, [RSP+#]", to_hex(windows_xmm_save_base + 8 * windows_xmm_slot_bytes) )); + APPEND_M(str( "MOVDQU XMM15, [RSP+#]", to_hex(windows_xmm_save_base + 9 * windows_xmm_slot_bytes) )); + } #endif APPEND_M(str( "MOV RSP, [RSP]" )); } diff --git a/src/uint128_t/uint128_t.cpp b/src/uint128_t/uint128_t.cpp index 89b90be8..0508952f 100644 --- a/src/uint128_t/uint128_t.cpp +++ b/src/uint128_t/uint128_t.cpp @@ -435,6 +435,10 @@ std::string uint128_t::str(uint8_t base, const unsigned int & len) const{ std::pair qr(*this, uint128_0); do{ qr = divmod(qr.first, base); + // Motivation: keep digit->char conversion explicit instead of relying on + // string-literal indexing + implicit char promotion. This is ABI/endianness + // agnostic and safe on x86-64 Linux/macOS/Windows, and performance is + // unchanged in practice since divmod dominates this formatting loop. uint8_t digit = static_cast(qr.second); char c = (digit < 10) ? static_cast('0' + digit) : static_cast('a' + (digit - 10)); diff --git a/src/vdf.h b/src/vdf.h index 38bcafca..22ef0fc3 100644 --- a/src/vdf.h +++ b/src/vdf.h @@ -53,8 +53,6 @@ #include #include #include - -#include #include #include "proof_common.h" #include "provers.h" diff --git a/src/vdf_base_integer.cpp b/src/vdf_base_integer.cpp deleted file mode 100644 index 2e4b02b1..00000000 --- a/src/vdf_base_integer.cpp +++ /dev/null @@ -1,342 +0,0 @@ -#include "vdf_base.hpp" - -#include - -#include "picosha2.h" -#include "proof_common.h" -#include "primetest.h" - -#include - -static void normalize_form(integer& a, integer& b, integer& c) { - integer r = (a - b) / (a << 1); - integer A = a; - integer B = b + ((r * a) << 1); - integer C = a * r * r + b * r + c; - a = A; - b = B; - c = C; -} - -static void reduce_form_impl(integer& a, integer& b, integer& c) { - integer s = (c + b) / (c << 1); - integer A = c; - integer B = ((s * c) << 1) - b; - integer C = c * s * s - b * s + a; - a = A; - b = B; - c = C; -} - -void reduce_form(integer& a, integer& b, integer& c) { - normalize_form(a, b, c); - while (a > c || (a == c && b < 0)) { - reduce_form_impl(a, b, c); - } - normalize_form(a, b, c); -} - -integer::integer(const string& s) { - mpz_init(impl); - int res = mpz_set_str(impl, s.c_str(), 0); - assert(res == 0); - (void)res; -} - -integer::integer(const std::vector v) { - mpz_init(impl); - mpz_import(impl, v.size(), 1, sizeof(v[0]), 1, 0, &v[0]); -} - -integer::integer(const vector& data) { - mpz_init(impl); - mpz_import(impl, data.size(), -1, 8, 0, 0, &data[0]); -} - -integer::integer(const uint8_t *bytes, size_t size) { - mpz_init(impl); - mpz_import(impl, size, 1, 1, 1, 0, bytes); -} - -vector integer::to_vector() const { - vector res; - res.resize(mpz_sizeinbase(impl, 2) / 64 + 1, 0); - - size_t count = 0; - mpz_export(res.data(), &count, -1, 8, 0, 0, impl); - res.resize(count); - - return res; -} - -vector integer::to_bytes() const { - vector res((mpz_sizeinbase(impl, 2) + 7) / 8); - mpz_export(res.data(), nullptr, 1, 1, 0, 0, impl); - return res; -} - -integer& integer::operator=(int64 i) { - mpz_set_si(impl, i); - return *this; -} - -integer& integer::operator=(const string& s) { - int res = mpz_set_str(impl, s.c_str(), 0); - assert(res == 0); - (void)res; - return *this; -} - -void integer::set_bit(int index, bool value) { - if (value) { - mpz_setbit(impl, index); - } else { - mpz_clrbit(impl, index); - } -} - -bool integer::get_bit(int index) { - return mpz_tstbit(impl, index); -} - -string integer::to_string() const { - string res_string = "0x"; - res_string.resize(res_string.size() + mpz_sizeinbase(impl, 16) + 2); - - mpz_get_str(&(res_string[2]), 16, impl); - - if (res_string.substr(0, 3) == "0x-") { - res_string.at(0) = '-'; - res_string.at(1) = '0'; - res_string.at(2) = 'x'; - } - - return res_string.c_str(); -} - -string integer::to_string_dec() const { - string res_string; - // mpz_sizeinbase() excludes sign; reserve extra for '-' and trailing '\0'. - res_string.resize(mpz_sizeinbase(impl, 10) + 2); - mpz_get_str(&(res_string[0]), 10, impl); - return res_string.c_str(); -} - -integer& integer::operator+=(const integer& t) { - mpz_add(impl, impl, t.impl); - return *this; -} - -integer integer::operator+(const integer& t) const { - integer res; - mpz_add(res.impl, impl, t.impl); - return res; -} - -integer& integer::operator-=(const integer& t) { - mpz_sub(impl, impl, t.impl); - return *this; -} - -integer integer::operator-(const integer& t) const { - integer res; - mpz_sub(res.impl, impl, t.impl); - return res; -} - -integer& integer::operator*=(const integer& t) { - mpz_mul(impl, impl, t.impl); - return *this; -} - -integer integer::operator*(const integer& t) const { - integer res; - mpz_mul(res.impl, impl, t.impl); - return res; -} - -integer& integer::operator<<=(int i) { - assert(i >= 0); - mpz_mul_2exp(impl, impl, i); - return *this; -} - -integer integer::operator<<(int i) const { - assert(i >= 0); - integer res; - mpz_mul_2exp(res.impl, impl, i); - return res; -} - -integer integer::operator-() const { - integer res; - mpz_neg(res.impl, impl); - return res; -} - -integer& integer::operator/=(const integer& t) { - mpz_fdiv_q(impl, impl, t.impl); - return *this; -} - -integer integer::operator/(const integer& t) const { - integer res; - mpz_fdiv_q(res.impl, impl, t.impl); - return res; -} - -integer& integer::operator>>=(int i) { - assert(i >= 0); - mpz_fdiv_q_2exp(impl, impl, i); - return *this; -} - -integer integer::operator>>(int i) const { - assert(i >= 0); - integer res; - mpz_fdiv_q_2exp(res.impl, impl, i); - return res; -} - -integer& integer::operator%=(const integer& t) { - mpz_mod(impl, impl, t.impl); - return *this; -} - -integer integer::operator%(const integer& t) const { - integer res; - mpz_mod(res.impl, impl, t.impl); - return res; -} - -integer integer::fdiv_r(const integer& t) const { - integer res; - mpz_fdiv_r(res.impl, impl, t.impl); - return res; -} - -bool integer::prime() const { - return is_prime_bpsw(impl) != 0; -} - -bool integer::operator<(const integer& t) const { - return mpz_cmp(impl, t.impl) < 0; -} - -bool integer::operator<=(const integer& t) const { - return mpz_cmp(impl, t.impl) <= 0; -} - -bool integer::operator==(const integer& t) const { - return mpz_cmp(impl, t.impl) == 0; -} - -bool integer::operator>=(const integer& t) const { - return mpz_cmp(impl, t.impl) >= 0; -} - -bool integer::operator>(const integer& t) const { - return mpz_cmp(impl, t.impl) > 0; -} - -bool integer::operator!=(const integer& t) const { - return mpz_cmp(impl, t.impl) != 0; -} - -bool integer::operator<(int i) const { - return mpz_cmp_si(impl, i) < 0; -} - -bool integer::operator<=(int i) const { - return mpz_cmp_si(impl, i) <= 0; -} - -bool integer::operator==(int i) const { - return mpz_cmp_si(impl, i) == 0; -} - -bool integer::operator>=(int i) const { - return mpz_cmp_si(impl, i) >= 0; -} - -bool integer::operator>(int i) const { - return mpz_cmp_si(impl, i) > 0; -} - -bool integer::operator!=(int i) const { - return mpz_cmp_si(impl, i) != 0; -} - -int integer::num_bits() const { - return mpz_sizeinbase(impl, 2); -} - -form form::from_abd(const integer& t_a, const integer& t_b, const integer& d) { - form res; - res.a = t_a; - res.b = t_b; - res.c = (t_b * t_b - d); - - if (t_a <= integer(0)) { - throw std::runtime_error("Invalid form. Positive a"); - } - if (res.c % (t_a << 2) != integer(0)) { - throw std::runtime_error("Invalid form. Can't find c."); - } - - res.c /= (t_a << 2); - res.reduce(); - return res; -} - -form form::identity(const integer& d) { - return from_abd(integer(1), integer(1), d); -} - -void form::reduce() { - reduce_form(a, b, c); -} - -bool form::is_reduced() { - int a_cmp_c = mpz_cmp(a.impl, c.impl); - if (a_cmp_c < 0 || (a_cmp_c == 0 && mpz_sgn(b.impl) >= 0)) { - if (mpz_cmpabs(a.impl, b.impl) > 0 || mpz_cmp(a.impl, b.impl) == 0) { - return true; - } - } - return false; -} - -form form::inverse() const { - form res = *this; - res.b = -res.b; - res.reduce(); - return res; -} - -void form::assert_valid(const integer& d) { - assert(check_valid(d)); -} - -bool form::operator==(const form& f) const { - return a == f.a && b == f.b && c == f.c; -} - -bool form::operator<(const form& f) const { - return std::make_tuple(a, b, c) < std::make_tuple(f.a, f.b, f.c); -} - -int form::hash() const { - const auto c_vector = c.to_vector(); - uint64 res = c_vector.empty() ? 0 : c_vector[0]; - return int((res >> 4) & ((1ull << 31) - 1)); -} - -uint64_t Prover::GetBlock(uint64_t i, uint64_t k, uint64_t T, integer& B) -{ - integer res = FastPow(2, T - k * (i + 1), B); - mpz_mul_2exp(res.impl, res.impl, k); - res = res / B; - auto res_vector = res.to_vector(); - return res_vector.empty() ? 0 : res_vector[0]; -} From 3f22222054eeccdbfa77e1ea6d26d16a184fd099 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Wed, 11 Feb 2026 21:45:38 -0800 Subject: [PATCH 39/78] fix windows avx512 add table rip-relative access Include CHIA_WINDOWS in the avx512_add_table addressing branch so Windows emits LEA+ADD RIP-relative access instead of absolute table addressing. Co-authored-by: Cursor --- src/asm_avx512_ifma.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/asm_avx512_ifma.h b/src/asm_avx512_ifma.h index 8041b257..1707c52c 100644 --- a/src/asm_avx512_ifma.h +++ b/src/asm_avx512_ifma.h @@ -625,7 +625,7 @@ void add(reg_alloc regs, avx512_integer in_a, avx512_integer in_b, avx512_intege //temp_1 has the address of the table entry APPEND_M(str( "SHL `temp_0, 5" )); //multiply by 32 to convert the index to a byte offset - #ifdef CHIAOSX + #if defined(CHIAOSX) || defined(CHIA_WINDOWS) APPEND_M(str( "LEA `temp_1, [RIP+avx512_add_table]" )); //base of the table APPEND_M(str( "ADD `temp_1, `temp_0")); //address of the table entry #else From 73f25855e5188855cdf8ef6fb99dbc16488f8a03 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Wed, 11 Feb 2026 22:06:01 -0800 Subject: [PATCH 40/78] Remove unused max_test_iteration in 2weso_test. Drop dead local state that was computed and immediately discarded to avoid implying a missing iteration guard. Co-authored-by: Cursor --- src/2weso_test.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/2weso_test.cpp b/src/2weso_test.cpp index 04dd254a..21a13ecd 100644 --- a/src/2weso_test.cpp +++ b/src/2weso_test.cpp @@ -54,8 +54,6 @@ int main(int argc, char const* argv[]) try std::atomic stopped = false; fast_algorithm = false; two_weso = true; - const uint64_t max_test_iteration = 100 * iter_multiplier; - (void)max_test_iteration; TwoWesolowskiCallback weso(D, f); FastStorage* fast_storage = NULL; std::thread vdf_worker(repeated_square, 0, f, D, L, &weso, fast_storage, std::ref(stopped)); From 564570392fd2331b4133d10067b75b3286457896 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Wed, 11 Feb 2026 22:06:54 -0800 Subject: [PATCH 41/78] fix gcd_unsigned compare against end_index Use end_index instead of size in the jump-table compare to match the mapped index logic and avoid incorrect branch selection. Co-authored-by: Cursor --- src/asm_gcd_unsigned.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/asm_gcd_unsigned.h b/src/asm_gcd_unsigned.h index d76eafec..303ef734 100644 --- a/src/asm_gcd_unsigned.h +++ b/src/asm_gcd_unsigned.h @@ -465,7 +465,7 @@ void gcd_unsigned( ++mapped_size; } - APPEND_M(str( "CMP `tmp, #", size )); + APPEND_M(str( "CMP `tmp, #", end_index )); APPEND_M(str( "JE ")+asmprefix+str("multiply_uv_size_#", mapped_size )); } From afcd78485114d0cca95e5505ce8c92a9abe80c83 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Wed, 11 Feb 2026 22:37:04 -0800 Subject: [PATCH 42/78] Harden callback state synchronization and update build/runtime tuning docs. This captures the current branch updates, including the TwoWesolowski position-locking fix and related CMake/parameter/readme adjustments for current CI work. Co-authored-by: Cursor --- README.md | 1 + src/CMakeLists.txt | 6 +++++- src/callback.h | 13 ++++++++++--- src/parameters.h | 3 +++ 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7631e6e5..35a9bec5 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ For direct CMake builds, the following options are available: - `BUILD_VDF_TESTS` - build `1weso_test`, `2weso_test`, and `prover_test` - `BUILD_HW_TOOLS` - build hardware timelord tools - `ENABLE_GNU_ASM` - enable GNU-style asm pipeline on x86/x64 (enabled by default) +- `GENERATE_ASM_TRACKING_DATA` - enable `track_asm()` instrumentation in generated asm (off by default to avoid hot-loop overhead) Example: diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f5a11220..74c1a2e4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,6 +6,7 @@ option(BUILD_VDF_BENCH "Build the vdf_bench binary" OFF) option(BUILD_VDF_TESTS "Build vdf test binaries (1weso/2weso/prover)" OFF) option(BUILD_HW_TOOLS "Build hardware timelord tools" OFF) option(ENABLE_GNU_ASM "Enable GNU-style asm pipeline on x86/x64" ON) +option(GENERATE_ASM_TRACKING_DATA "Emit asm tracking instrumentation data from compile_asm" OFF) option(HARDENING "Enable hardening" OFF) set(CMAKE_CXX_STANDARD 17) @@ -83,7 +84,10 @@ endif() # CMake 3.14+ include(FetchContent) -set(VDF_COMMON_DEFINITIONS VDF_MODE=0 FAST_MACHINE=1 GENERATE_ASM_TRACKING_DATA=1) +set(VDF_COMMON_DEFINITIONS VDF_MODE=0 FAST_MACHINE=1) +if(GENERATE_ASM_TRACKING_DATA) + list(APPEND VDF_COMMON_DEFINITIONS GENERATE_ASM_TRACKING_DATA=1) +endif() set(VDF_COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/refcode/lzcnt.c ) diff --git a/src/callback.h b/src/callback.h index 2c21a80c..8bcfabaa 100644 --- a/src/callback.h +++ b/src/callback.h @@ -136,12 +136,18 @@ class TwoWesolowskiCallback: public WesolowskiCallback { } void IncreaseConstants(uint64_t num_iters) { + std::lock_guard lk(forms_mutex); kl = 100; switch_iters = num_iters; switch_index = num_iters / 10; } int GetPosition(uint64_t power) { + std::lock_guard lk(forms_mutex); + return GetPositionUnlocked(power); + } + + int GetPositionUnlocked(uint64_t power) const { if (switch_iters == -1 || power < switch_iters) { return power / 10; } else { @@ -151,7 +157,7 @@ class TwoWesolowskiCallback: public WesolowskiCallback { form GetFormCopy(uint64_t power) { std::lock_guard lk(forms_mutex); - const int pos = GetPosition(power); + const int pos = GetPositionUnlocked(power); if (pos < 0 || static_cast(pos) >= forms_capacity) { throw std::runtime_error("TwoWesolowskiCallback::GetFormCopy out of bounds"); } @@ -159,17 +165,18 @@ class TwoWesolowskiCallback: public WesolowskiCallback { } bool LargeConstants() { + std::lock_guard lk(forms_mutex); return kl == 100; } void OnIteration(int type, void *data, uint64_t iteration) { iteration++; + std::lock_guard lk(forms_mutex); if (iteration % kl == 0) { - const int pos = GetPosition(iteration); + const int pos = GetPositionUnlocked(iteration); if (pos < 0 || static_cast(pos) >= forms_capacity) { throw std::runtime_error("TwoWesolowskiCallback::OnIteration out of bounds"); } - std::lock_guard lk(forms_mutex); form* mulf = &forms[static_cast(pos)]; SetForm(type, data, mulf); } diff --git a/src/parameters.h b/src/parameters.h index 8d0059d7..07a49de7 100644 --- a/src/parameters.h +++ b/src/parameters.h @@ -43,6 +43,9 @@ inline bool env_flag(const char* name) { if (!value) { return false; } + if (value[0] == '\0') { + return false; + } if (value[0] == '1' || value[0] == 'y' || value[0] == 'Y' || value[0] == 't' || value[0] == 'T') { return true; } From c3e10d25f1d19305a9dccb6c67ca210f162a0fa4 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Wed, 11 Feb 2026 23:14:10 -0800 Subject: [PATCH 43/78] Guard POSIX-only emulator hardware targets on Windows. Prevent `emu_hw_test` and `emu_hw_vdf_client` from being defined on Windows so CMake does not try to compile sources that depend on POSIX headers. Co-authored-by: Cursor --- src/CMakeLists.txt | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 74c1a2e4..ecce214e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -195,7 +195,7 @@ endif() set(HAVE_BOOST_HEADERS FALSE) set(NEED_BOOST_HEADERS FALSE) -if(BUILD_VDF_CLIENT OR BUILD_VDF_TESTS OR BUILD_HW_TOOLS) +if(BUILD_VDF_CLIENT OR BUILD_VDF_TESTS) set(NEED_BOOST_HEADERS TRUE) endif() @@ -350,21 +350,23 @@ if(BUILD_HW_TOOLS) endif() endif() - add_executable(emu_hw_test - ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_test.cpp - ) - target_sources(emu_hw_test PRIVATE ${HW_COMMON_SOURCES} ${EMU_SOURCES} ${VDF_ASM_SOURCES} ${VDF_COMMON_SOURCES}) - target_compile_definitions(emu_hw_test PRIVATE ${VDF_COMMON_DEFINITIONS}) - target_include_directories(emu_hw_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/hw ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222) - target_link_libraries(emu_hw_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + if(NOT WIN32) + add_executable(emu_hw_test + ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_test.cpp + ) + target_sources(emu_hw_test PRIVATE ${HW_COMMON_SOURCES} ${EMU_SOURCES} ${VDF_ASM_SOURCES} ${VDF_COMMON_SOURCES}) + target_compile_definitions(emu_hw_test PRIVATE ${VDF_COMMON_DEFINITIONS}) + target_include_directories(emu_hw_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/hw ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222) + target_link_libraries(emu_hw_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) - add_executable(emu_hw_vdf_client - ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_vdf_client.cpp - ) - target_sources(emu_hw_vdf_client PRIVATE ${HW_COMMON_SOURCES} ${EMU_SOURCES} ${VDF_ASM_SOURCES} ${VDF_COMMON_SOURCES}) - target_compile_definitions(emu_hw_vdf_client PRIVATE ${VDF_COMMON_DEFINITIONS}) - target_include_directories(emu_hw_vdf_client PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/hw ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222) - target_link_libraries(emu_hw_vdf_client PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + add_executable(emu_hw_vdf_client + ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_vdf_client.cpp + ) + target_sources(emu_hw_vdf_client PRIVATE ${HW_COMMON_SOURCES} ${EMU_SOURCES} ${VDF_ASM_SOURCES} ${VDF_COMMON_SOURCES}) + target_compile_definitions(emu_hw_vdf_client PRIVATE ${VDF_COMMON_DEFINITIONS}) + target_include_directories(emu_hw_vdf_client PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/hw ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222) + target_link_libraries(emu_hw_vdf_client PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + endif() endif() add_executable(verifier_test From 16b5466304dc0d8d846192affea8940eebaf4bc9 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Wed, 11 Feb 2026 23:58:33 -0800 Subject: [PATCH 44/78] Initialize FastAlgorithmCallback forms_capacity. Set forms_capacity when allocating FastAlgorithmCallback forms so all WesolowskiCallback subclasses consistently initialize capacity metadata for safe bounds checks. Co-authored-by: Cursor --- src/callback.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/callback.h b/src/callback.h index 8bcfabaa..53c203ac 100644 --- a/src/callback.h +++ b/src/callback.h @@ -200,6 +200,7 @@ class FastAlgorithmCallback : public WesolowskiCallback { buckets_begin.push_back(buckets_begin[buckets_begin.size() - 1] + bucket_size2 * window_size); } int space_needed = window_size * (bucket_size1 + bucket_size2 * (segments - 1)); + forms_capacity = static_cast(space_needed); forms.reset(new form[space_needed]); checkpoints.reset(new form[1 << 18]); From 96abd395a6ab42b2096f8ed813d36e8e36c1ad04 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Thu, 12 Feb 2026 00:32:36 -0800 Subject: [PATCH 45/78] Harden macOS/Windows gcd_unsigned dispatch bounds check. Add the same a_end_index range guard used on Linux before the CMP/JE chain so out-of-range values jump to the error path instead of falling through to a kernel label. Co-authored-by: Cursor --- src/asm_gcd_unsigned.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/asm_gcd_unsigned.h b/src/asm_gcd_unsigned.h index 303ef734..f6bc1019 100644 --- a/src/asm_gcd_unsigned.h +++ b/src/asm_gcd_unsigned.h @@ -455,7 +455,10 @@ void gcd_unsigned( #if defined(CHIAOSX) || defined(CHIA_WINDOWS) APPEND_M(str( ".text" )); + string bad_end_index_label = track_asm( "gcd_unsigned invalid a_end_index", m.alloc_error_label() ); APPEND_M(str( "MOV `tmp, `spill_a_end_index" )); + APPEND_M(str( "CMP `tmp, #", to_hex(int_size-1) )); + APPEND_M(str( "JA #", bad_end_index_label )); for (int end_index=0;end_index Date: Thu, 12 Feb 2026 00:35:18 -0800 Subject: [PATCH 46/78] Define CHIAOSX for macOS CMake asm generation. Match the Makefile behavior so compile_asm emits Mach-O-compatible assembly on Intel macOS instead of falling back to Linux/ELF code paths. Co-authored-by: Cursor --- src/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ecce214e..e054c818 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -37,6 +37,10 @@ endif() find_package(Threads REQUIRED) +if(APPLE) + add_compile_definitions(CHIAOSX) +endif() + if(WIN32) add_compile_definitions(CHIA_WINDOWS) set(MPIR_LIBRARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../mpir_gc_x64") @@ -106,6 +110,8 @@ if(ENABLE_GNU_ASM AND (CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|AMD64|i[3-6]86)$ target_compile_definitions(compile_asm PRIVATE ${VDF_COMMON_DEFINITIONS}) if(WIN32) target_compile_definitions(compile_asm PRIVATE CHIA_WINDOWS) + elseif(APPLE) + target_compile_definitions(compile_asm PRIVATE CHIAOSX) endif() target_link_libraries(compile_asm PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) if(WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang") From 01e8da94544ddd5b176eb8747af56c8b03c91671 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Thu, 12 Feb 2026 01:04:40 -0800 Subject: [PATCH 47/78] Refine Windows asm argument handling and remove unused SEH include. Allow asm_function Windows stack-arg loading to be toggled for internal call sites, and drop dead from threading since no SEH constructs are used. Co-authored-by: Cursor --- src/asm_vm.h | 22 +++++++++++++++++----- src/threading.h | 3 --- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/asm_vm.h b/src/asm_vm.h index eb1cd2b9..4e8930bc 100644 --- a/src/asm_vm.h +++ b/src/asm_vm.h @@ -54,18 +54,29 @@ struct asm_function { bool d_align_stack=true; bool d_return_error_code=true; + bool d_windows_stack_args=true; //the scratch area ends at RSP (i.e. the last byte is at address RSP-1) //RSP is 64-byte aligned //RSP must be preserved but all other registers can be changed // - //the arguments are stored in: RDI, RSI, RDX, RCX, R8, R9 + //non-Windows: args are in RDI, RSI, RDX, RCX, R8, R9 + //Windows: args 1-4 are in RCX, RDX, R8, R9; args 5+ are ABI stack args + //that may be loaded into R10/R11 by the prologue for convenience. //each argument is up to 8 bytes - asm_function(string t_name, int num_args=0, int num_regs=15, bool align_stack=true, bool return_error_code=true) { + asm_function( + string t_name, + int num_args=0, + int num_regs=15, + bool align_stack=true, + bool return_error_code=true, + bool windows_stack_args=true + ) { EXPAND_MACROS_SCOPE; d_align_stack=align_stack; d_return_error_code=return_error_code; + d_windows_stack_args=windows_stack_args; static bool outputted_header=false; if (!outputted_header) { @@ -92,11 +103,12 @@ struct asm_function { args.push_back(r); } #ifdef CHIA_WINDOWS - // Load 5th+ args from the stack (Windows x64 calling convention). - if (num_args > 4) { + // For ABI entry points, pull args 5+ from the caller stack per Win64 ABI. + // Internal asm-to-asm calls may pass args 5/6 in R10/R11 and opt out. + if (d_windows_stack_args && num_args > 4) { APPEND_M(str( "MOV R10, [RSP+0x28]" )); } - if (num_args > 5) { + if (d_windows_stack_args && num_args > 5) { APPEND_M(str( "MOV R11, [RSP+0x30]" )); } #endif diff --git a/src/threading.h b/src/threading.h index 08c4869c..c2fc0987 100644 --- a/src/threading.h +++ b/src/threading.h @@ -3,9 +3,6 @@ #include "alloc.hpp" #include -#ifdef _WIN32 -#include -#endif //mp_limb_t is an unsigned integer static_assert(sizeof(mp_limb_t)==8, ""); From 24de3c8bc3d681d4b237e9ba9ada95b321322642 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Thu, 12 Feb 2026 13:25:45 -0800 Subject: [PATCH 48/78] ci(hw): add cross-platform HW workflow and FT4222 installers. Introduce dedicated Ubuntu/macOS/Windows hardware CI jobs and reusable FT4222 download scripts to make HW artifact builds consistent across runners. Co-authored-by: Cursor --- .github/workflows/hw-build.yml | 150 +++++++++++++++++++++++++-- scripts/get-libft4222.ps1 | 174 ++++++++++++++++++++++++++++++++ scripts/get-libft4222.sh | 179 +++++++++++++++++++++++++++++++++ 3 files changed, 494 insertions(+), 9 deletions(-) create mode 100644 scripts/get-libft4222.ps1 create mode 100755 scripts/get-libft4222.sh diff --git a/.github/workflows/hw-build.yml b/.github/workflows/hw-build.yml index 268191b1..34a5265b 100644 --- a/.github/workflows/hw-build.yml +++ b/.github/workflows/hw-build.yml @@ -22,7 +22,7 @@ permissions: jobs: build-hw: - name: Build HW VDF Client + name: Build HW VDF Client (Ubuntu) runs-on: [ubuntu-22.04] steps: - name: Checkout code @@ -43,21 +43,25 @@ jobs: - name: Install deps run: | sudo apt-get update - sudo apt-get install -y build-essential cmake libgmp-dev libboost-system-dev + sudo apt-get install -y build-essential cmake libgmp-dev - name: Download USB drivers - run: | - mkdir libft4222 - cd libft4222 - wget https://download.chia.net/vdf/libft4222-linux-1.4.4.170.tgz - tar -xvzf libft4222-linux-1.4.4.170.tgz - ln -s ${{ github.workspace }}/libft4222 ${{ github.workspace }}/src/hw/libft4222 - ln -s ${{ github.workspace }}/libft4222/build-x86_64/libft4222.so.1.4.4.170 ${{ github.workspace }}/libft4222/build-x86_64/libft4222.so + run: ./scripts/get-libft4222.sh install - name: Compile working-directory: "${{ github.workspace }}/src" run: make -f Makefile.vdf-client emu_hw_test hw_test emu_hw_vdf_client hw_vdf_client + - name: Smoke test + working-directory: "${{ github.workspace }}/src" + run: | + # CI runners do not have FT4222 hardware attached; only validate binaries exist. + test -x ./hw_vdf_client + test -x ./hw_test + echo "Running emu_hw_test" + ./emu_hw_test 1 2000 + ./emu_hw_vdf_client --list + - name: Upload Artifacts uses: actions/upload-artifact@v5 with: @@ -119,3 +123,131 @@ jobs: glue_url: ${{ secrets.GLUE_API_URL }} glue_project: "chiavdf-hw" glue_path: "trigger" + + build-hw-macos-arm64: + name: Build HW VDF Client (macOS arm64) + runs-on: [macos-13-arm64] + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - uses: Chia-Network/actions/setup-python@main + name: Install Python + with: + python-version: "3.10" + + - name: Set Env + uses: Chia-Network/actions/setjobenv@main + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install deps + run: | + brew ls --versions gmp >/dev/null 2>&1 || brew install gmp + + - name: Download USB drivers (FT4222H) + run: ./scripts/get-libft4222.sh install + + - name: Compile + working-directory: "${{ github.workspace }}/src" + run: make -f Makefile.vdf-client emu_hw_test hw_test emu_hw_vdf_client hw_vdf_client + + - name: Smoke test + working-directory: "${{ github.workspace }}/src" + run: | + # CI runners do not have FT4222 hardware attached; only validate binaries exist. + test -x ./hw_vdf_client + test -x ./hw_test + echo "Running emu_hw_test" + ./emu_hw_test 1 2000 + ./emu_hw_vdf_client --list + + - name: Upload Artifacts + uses: actions/upload-artifact@v5 + with: + name: hw-vdf-macos-arm64 + path: | + ${{ github.workspace }}/src/emu_hw_test + ${{ github.workspace }}/src/hw_test + ${{ github.workspace }}/src/hw_vdf_client + ${{ github.workspace }}/src/emu_hw_vdf_client + ${{ github.workspace }}/src/hw/libft4222/libft4222.dylib + ${{ github.workspace }}/src/hw/libft4222/libft4222.1.4.4.190.dylib + ${{ github.workspace }}/src/hw/libft4222/libftd2xx.dylib + + build-hw-windows: + name: Build HW VDF Client (Windows) + runs-on: [windows-latest] + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 1 + + - name: Set Env + uses: Chia-Network/actions/setjobenv@main + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Checkout mpir for Windows + uses: actions/checkout@v6 + with: + repository: Chia-Network/mpir_gc_x64 + fetch-depth: 1 + path: mpir_gc_x64 + + - name: Install LLVM and Ninja on Windows + shell: pwsh + run: | + $llvmBin = "C:\Program Files\LLVM\bin\clang-cl.exe" + $ninjaBin = "C:\ProgramData\chocolatey\bin\ninja.exe" + if (-not (Test-Path $llvmBin) -or -not (Test-Path $ninjaBin)) { + choco install llvm ninja -y + } + "C:\Program Files\LLVM\bin" | Out-File -Append -FilePath $env:GITHUB_PATH + + - name: Set up MSVC environment (Windows SDK + CRT libs) + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + + - name: Download USB drivers (FT4222H) + run: powershell -ExecutionPolicy Bypass -File scripts/get-libft4222.ps1 install + + - name: Configure hw tools + shell: pwsh + run: | + cmake -S src -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_TRY_COMPILE_CONFIGURATION=Release -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_ASM_COMPILER=clang-cl -DBUILD_PYTHON=OFF -DBUILD_CHIAVDFC=OFF -DBUILD_HW_TOOLS=ON + + - name: Build hw tools + shell: pwsh + run: | + cmake --build build --target emu_hw_test + cmake --build build --target hw_test + + - name: Smoke test + working-directory: "${{ github.workspace }}/build" + shell: pwsh + run: | + $dllPaths = @() + if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } + if (Test-Path "$env:GITHUB_WORKSPACE\src\hw\libft4222") { $dllPaths += "$env:GITHUB_WORKSPACE\src\hw\libft4222" } + if ($dllPaths.Count -gt 0) { $env:PATH = ($dllPaths -join ';') + ';' + $env:PATH } + if (Test-Path ".\hw_test.exe") { Write-Host "hw_test.exe present" } + Write-Host "Running emu_hw_test" + .\emu_hw_test.exe 1 2000 + Write-Host "emu_hw_test completed" + + - name: Upload Artifacts + uses: actions/upload-artifact@v5 + with: + name: hw-vdf-windows + path: | + ${{ github.workspace }}/build/emu_hw_test.exe + ${{ github.workspace }}/build/hw_test.exe + ${{ github.workspace }}/src/hw/libft4222/libft4222.dll + ${{ github.workspace }}/src/hw/libft4222/ftd2xx.dll + ${{ github.workspace }}/src/hw/libft4222/libft4222.lib + ${{ github.workspace }}/src/hw/libft4222/ftd2xx.lib diff --git a/scripts/get-libft4222.ps1 b/scripts/get-libft4222.ps1 new file mode 100644 index 00000000..1526fea8 --- /dev/null +++ b/scripts/get-libft4222.ps1 @@ -0,0 +1,174 @@ +Param( + [Parameter(Mandatory = $false)] + [ValidateSet("install", "clean")] + [string]$Action = "install" +) + +$ErrorActionPreference = "Stop" + +$RootDir = Resolve-Path (Join-Path $PSScriptRoot "..") +$SrcDir = Join-Path $RootDir "src" +$WorkDir = Join-Path $SrcDir "libft4222" +$HwDir = Join-Path $SrcDir "hw\libft4222" + +$ZipUrl = "https://download.chia.net/vdf/LibFT4222-v1.4.8.zip" +$ZipPath = Join-Path $WorkDir "LibFT4222-v1.4.8.zip" +$ExtractDir = Join-Path $WorkDir "extract" + +Add-Type -AssemblyName System.IO.Compression.FileSystem + +function Ensure-Dir { + param([string]$Path) + if (-not (Test-Path $Path)) { + New-Item -ItemType Directory -Path $Path | Out-Null + } +} + +function Choose-Best { + param([System.IO.FileInfo[]]$Items) + if (-not $Items -or $Items.Count -eq 0) { + return $null + } + $preferred = $Items | Where-Object { $_.FullName -match "(x64|amd64|win64)" } + if ($preferred -and $preferred.Count -gt 0) { + return $preferred[0] + } + return $Items[0] +} + +function Find-Header { + param( + [string]$BaseName, + [string[]]$Alternates = @() + ) + $names = @($BaseName) + $Alternates + foreach ($name in $names) { + $match = Get-ChildItem -Path $ExtractDir -Recurse -File | + Where-Object { $_.Name -ieq $name } | + Select-Object -First 1 + if ($match) { + return $match + } + } + return $null +} + +function Test-ZipValid { + param([string]$Path) + if (-not (Test-Path $Path)) { + return $false + } + $zip = $null + try { + $zip = [System.IO.Compression.ZipFile]::OpenRead($Path) + $null = $zip.Entries.Count + return $true + } catch { + return $false + } finally { + if ($zip) { + $zip.Dispose() + } + } +} + +function Download-With-Retry { + param( + [string]$Url, + [string]$Path, + [int]$Attempts = 3 + ) + for ($attempt = 1; $attempt -le $Attempts; $attempt++) { + if (Test-Path $Path) { + Remove-Item $Path -Force + } + try { + Invoke-WebRequest -Uri $Url -OutFile $Path -MaximumRedirection 5 + } catch { + if ($attempt -eq $Attempts) { + throw + } + Start-Sleep -Seconds (2 * $attempt) + continue + } + if (Test-ZipValid $Path) { + return + } + Write-Warning "Downloaded zip failed validation (attempt $attempt/$Attempts)." + Start-Sleep -Seconds (2 * $attempt) + } + throw "Failed to download a valid zip from $Url after $Attempts attempts." +} + +function Install-LibFT4222 { + Ensure-Dir $WorkDir + if (Test-Path $ExtractDir) { + Remove-Item $ExtractDir -Recurse -Force + } + + Download-With-Retry -Url $ZipUrl -Path $ZipPath -Attempts 3 + Expand-Archive -Path $ZipPath -DestinationPath $ExtractDir -Force + + $headers = @( + @{ Name = "libft4222.h"; Alternates = @() }, + @{ Name = "ftd2xx.h"; Alternates = @() }, + @{ Name = "WinTypes.h"; Alternates = @("wintypes.h") } + ) + foreach ($header in $headers) { + $match = Find-Header -BaseName $header.Name -Alternates $header.Alternates + if (-not $match) { + if ($header.Name -eq "WinTypes.h") { + $stubPath = Join-Path $WorkDir $header.Name + @" +#pragma once +#ifdef _WIN32 +#include +#endif +"@ | Set-Content -Path $stubPath -Encoding ASCII + continue + } + throw "Missing required header: $($header.Name)" + } + Copy-Item $match.FullName -Destination (Join-Path $WorkDir $header.Name) -Force + } + + $libftLib = Choose-Best (Get-ChildItem -Path $ExtractDir -Recurse -Filter "libft4222*.lib") + $ftdLib = Choose-Best (Get-ChildItem -Path $ExtractDir -Recurse -Filter "ftd2xx*.lib") + $libftDll = Choose-Best (Get-ChildItem -Path $ExtractDir -Recurse -Filter "libft4222*.dll") + $ftdDll = Choose-Best (Get-ChildItem -Path $ExtractDir -Recurse -Filter "ftd2xx*.dll") + + if (-not $libftLib -or -not $ftdLib) { + throw "Missing required .lib files in extracted package" + } + if (-not $libftDll -or -not $ftdDll) { + throw "Missing required .dll files in extracted package" + } + + Copy-Item $libftLib.FullName -Destination (Join-Path $WorkDir "libft4222.lib") -Force + Copy-Item $ftdLib.FullName -Destination (Join-Path $WorkDir "ftd2xx.lib") -Force + Copy-Item $libftDll.FullName -Destination (Join-Path $WorkDir "libft4222.dll") -Force + Copy-Item $ftdDll.FullName -Destination (Join-Path $WorkDir "ftd2xx.dll") -Force + + if (Test-Path $HwDir) { + Remove-Item $HwDir -Recurse -Force + } + Ensure-Dir $HwDir + + Copy-Item (Join-Path $WorkDir "*.h") -Destination $HwDir -Force + Copy-Item (Join-Path $WorkDir "*.lib") -Destination $HwDir -Force + Copy-Item (Join-Path $WorkDir "*.dll") -Destination $HwDir -Force +} + +function Clean-LibFT4222 { + if (Test-Path $WorkDir) { + Remove-Item $WorkDir -Recurse -Force + } + if (Test-Path $HwDir) { + Remove-Item $HwDir -Recurse -Force + } +} + +switch ($Action) { + "install" { Install-LibFT4222 } + "clean" { Clean-LibFT4222 } +} diff --git a/scripts/get-libft4222.sh b/scripts/get-libft4222.sh new file mode 100755 index 00000000..0bca8601 --- /dev/null +++ b/scripts/get-libft4222.sh @@ -0,0 +1,179 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +SRC_DIR="${ROOT_DIR}/src" +WORK_DIR="${SRC_DIR}/libft4222" +HW_DIR="${SRC_DIR}/hw/libft4222" + +# Upstream FT4222 driver downloads can be found at https://ftdichip.com/products/ft4222h/ +# on the Downloads tab in the middle of the page as of 2026-02-05. +# There is an updated Linux version available(v1.4.4.233) also as of 2026-02-05. +# We currently fetch known-good versions mirrored at download.chia.net. + +LINUX_URL="https://download.chia.net/vdf/libft4222-linux-1.4.4.170.tgz" +LINUX_ARCHIVE="${WORK_DIR}/libft4222-linux-1.4.4.170.tgz" +MAC_URL="https://download.chia.net/vdf/LibFT4222-mac-v1.4.4.190.zip" +MAC_ARCHIVE="${WORK_DIR}/LibFT4222-mac-v1.4.4.190.zip" +MAC_DMG="libft4222.1.4.4.190.dmg" + +usage() { + cat <<'EOF' +Usage: scripts/get-libft4222.sh + +install Download and place FT4222 driver headers/libs. +clean Remove downloaded artifacts and symlinks. +EOF +} + +need_cmd() { + if ! command -v "$1" >/dev/null 2>&1; then + echo "Missing required command: $1" >&2 + exit 1 + fi +} + +fetch_once() { + local url="$1" + local dest="$2" + if command -v curl >/dev/null 2>&1; then + curl -L -o "$dest" "$url" + elif command -v wget >/dev/null 2>&1; then + wget -O "$dest" "$url" + else + echo "Missing curl or wget for downloads" >&2 + exit 1 + fi +} + +validate_archive() { + local kind="$1" + local path="$2" + case "$kind" in + tgz) + tar -tzf "$path" >/dev/null 2>&1 + ;; + zip) + unzip -t "$path" >/dev/null 2>&1 + ;; + *) + echo "Unknown archive type: $kind" >&2 + return 1 + ;; + esac +} + +fetch_with_retry() { + local url="$1" + local dest="$2" + local kind="$3" + local attempts="${4:-3}" + local attempt=1 + + while [ "$attempt" -le "$attempts" ]; do + rm -f "$dest" + fetch_once "$url" "$dest" || true + if [ -f "$dest" ] && validate_archive "$kind" "$dest"; then + return 0 + fi + echo "Downloaded archive failed validation (attempt $attempt/$attempts)." >&2 + sleep $((2 * attempt)) + attempt=$((attempt + 1)) + done + + echo "Failed to download a valid archive from $url after $attempts attempts." >&2 + return 1 +} + +install_linux() { + need_cmd tar + + mkdir -p "$WORK_DIR" + fetch_with_retry "$LINUX_URL" "$LINUX_ARCHIVE" tgz 3 + tar -xzf "$LINUX_ARCHIVE" -C "$WORK_DIR" + + rm -rf "$HW_DIR" + ln -s "$WORK_DIR" "$HW_DIR" + ln -sf "$WORK_DIR/build-x86_64/libft4222.so.1.4.4.170" \ + "$WORK_DIR/build-x86_64/libft4222.so" +} + +install_macos() { + need_cmd unzip + need_cmd hdiutil + need_cmd install_name_tool + need_cmd codesign + + mkdir -p "$WORK_DIR" + fetch_with_retry "$MAC_URL" "$MAC_ARCHIVE" zip 3 + unzip -q "$MAC_ARCHIVE" -d "$WORK_DIR" + + local mount_dir="${WORK_DIR}/ft4222-mount" + local mounted=0 + cleanup_mount() { + if [ "$mounted" -eq 1 ]; then + hdiutil detach "$mount_dir" >/dev/null 2>&1 || true + mounted=0 + fi + } + trap cleanup_mount EXIT + + # If a previous run failed, try to detach before re-attaching. + hdiutil detach "$mount_dir" >/dev/null 2>&1 || true + mkdir -p "$mount_dir" + hdiutil attach -nobrowse -readonly -mountpoint "$mount_dir" "${WORK_DIR}/${MAC_DMG}" + mounted=1 + + cp "$mount_dir/ftd2xx.h" "$WORK_DIR/" + cp "$mount_dir/libft4222.h" "$WORK_DIR/" + cp "$mount_dir/WinTypes.h" "$WORK_DIR/" + cp "$mount_dir/build/libft4222.1.4.4.190.dylib" "$WORK_DIR/" + cp "$mount_dir/build/libftd2xx.dylib" "$WORK_DIR/" + cleanup_mount + trap - EXIT + + ln -sf "libft4222.1.4.4.190.dylib" "${WORK_DIR}/libft4222.dylib" + + install_name_tool -id "@rpath/libftd2xx.dylib" "${WORK_DIR}/libftd2xx.dylib" + install_name_tool -id "@rpath/libft4222.dylib" "${WORK_DIR}/libft4222.1.4.4.190.dylib" + install_name_tool -change "libftd2xx.dylib" "@rpath/libftd2xx.dylib" \ + "${WORK_DIR}/libft4222.1.4.4.190.dylib" + + # Clear provenance attributes and ad-hoc sign dylibs to avoid execution kills. + if command -v xattr >/dev/null 2>&1; then + xattr -dr com.apple.provenance "$WORK_DIR" || true + fi + codesign --force --sign - \ + "${WORK_DIR}/libftd2xx.dylib" \ + "${WORK_DIR}/libft4222.1.4.4.190.dylib" \ + "${WORK_DIR}/libft4222.dylib" + + rm -rf "$HW_DIR" + ln -s "$WORK_DIR" "$HW_DIR" +} + +clean_all() { + local mount_dir="${WORK_DIR}/ft4222-mount" + hdiutil detach "$mount_dir" >/dev/null 2>&1 || true + rm -rf "$WORK_DIR" + if [ -L "$HW_DIR" ] || [ -d "$HW_DIR" ]; then + rm -rf "$HW_DIR" + fi +} + +case "${1:-}" in + install) + case "$(uname -s)" in + Linux) install_linux ;; + Darwin) install_macos ;; + *) echo "Unsupported OS: $(uname -s)" >&2; exit 1 ;; + esac + ;; + clean) + clean_all + ;; + *) + usage + exit 1 + ;; +esac From 0a6a59552f180f73ef5fe486820603e1e151f1c0 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Thu, 12 Feb 2026 13:25:52 -0800 Subject: [PATCH 49/78] build(hw): refactor HW target wiring for cross-platform CMake and Make. Align HW target selection and symbol anchor handling so Linux/macOS/Windows builds resolve the same HW binaries and link paths reliably. Co-authored-by: Cursor --- src/CMakeLists.txt | 107 ++++++++++++++++++---------------- src/Makefile.vdf-client | 44 ++++++++++++-- src/vdf_hw_symbol_anchors.cpp | 24 ++++++++ 3 files changed, 120 insertions(+), 55 deletions(-) create mode 100644 src/vdf_hw_symbol_anchors.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e054c818..57718e18 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -42,7 +42,7 @@ if(APPLE) endif() if(WIN32) - add_compile_definitions(CHIA_WINDOWS) + add_compile_definitions(CHIA_WINDOWS NOMINMAX WIN32_LEAN_AND_MEAN) set(MPIR_LIBRARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../mpir_gc_x64") set(MPIR_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../mpir_gc_x64") include_directories( @@ -318,61 +318,70 @@ if(BUILD_HW_TOOLS) ${CMAKE_CURRENT_SOURCE_DIR}/hw/emu_funcs.cpp ${CMAKE_CURRENT_SOURCE_DIR}/hw/emu_runner.cpp ) + set(HW_VDF_ASM_SOURCES ${VDF_ASM_SOURCES}) + if(WIN32) + # Generated asm currently collides with lzcnt symbols for HW tool links on Windows. + set(HW_VDF_ASM_SOURCES) + endif() - if(NOT WIN32) - if(APPLE) - set(HW_LIBS - ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222/libft4222.dylib - ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222/libftd2xx.dylib - ) - else() - set(HW_LIBS - ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222/build-x86_64/libft4222.so - ) - endif() - - add_executable(hw_test - ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/hw/real_hw.cpp + if(WIN32) + set(HW_LIBS + ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222/libft4222.lib + ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222/ftd2xx.lib ) - target_sources(hw_test PRIVATE ${HW_COMMON_SOURCES} ${VDF_ASM_SOURCES} ${VDF_COMMON_SOURCES}) - target_compile_definitions(hw_test PRIVATE ${VDF_COMMON_DEFINITIONS}) - target_include_directories(hw_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/hw ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222) - target_link_libraries(hw_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads ${HW_LIBS}) - if(APPLE) - target_link_options(hw_test PRIVATE "-Wl,-rpath,@executable_path/hw/libft4222") - endif() - - add_executable(hw_vdf_client - ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_vdf_client.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/hw/real_hw.cpp + set(HW_SOCKET_LIBS ws2_32) + elseif(APPLE) + set(HW_LIBS + ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222/libft4222.dylib + ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222/libftd2xx.dylib ) - target_sources(hw_vdf_client PRIVATE ${HW_COMMON_SOURCES} ${VDF_ASM_SOURCES} ${VDF_COMMON_SOURCES}) - target_compile_definitions(hw_vdf_client PRIVATE ${VDF_COMMON_DEFINITIONS}) - target_include_directories(hw_vdf_client PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/hw ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222) - target_link_libraries(hw_vdf_client PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads ${HW_LIBS}) - if(APPLE) - target_link_options(hw_vdf_client PRIVATE "-Wl,-rpath,@executable_path/hw/libft4222") - endif() + set(HW_SOCKET_LIBS) + else() + set(HW_LIBS + ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222/build-x86_64/libft4222.so + ) + set(HW_SOCKET_LIBS) endif() - if(NOT WIN32) - add_executable(emu_hw_test - ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_test.cpp - ) - target_sources(emu_hw_test PRIVATE ${HW_COMMON_SOURCES} ${EMU_SOURCES} ${VDF_ASM_SOURCES} ${VDF_COMMON_SOURCES}) - target_compile_definitions(emu_hw_test PRIVATE ${VDF_COMMON_DEFINITIONS}) - target_include_directories(emu_hw_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/hw ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222) - target_link_libraries(emu_hw_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + add_executable(hw_test + ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/hw/real_hw.cpp + ) + target_sources(hw_test PRIVATE ${HW_COMMON_SOURCES} ${HW_VDF_ASM_SOURCES} ${VDF_COMMON_SOURCES}) + target_compile_definitions(hw_test PRIVATE ${VDF_COMMON_DEFINITIONS}) + target_include_directories(hw_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/hw ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222) + target_link_libraries(hw_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads ${HW_LIBS}) + if(APPLE) + target_link_options(hw_test PRIVATE "-Wl,-rpath,@executable_path/hw/libft4222") + endif() - add_executable(emu_hw_vdf_client - ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_vdf_client.cpp - ) - target_sources(emu_hw_vdf_client PRIVATE ${HW_COMMON_SOURCES} ${EMU_SOURCES} ${VDF_ASM_SOURCES} ${VDF_COMMON_SOURCES}) - target_compile_definitions(emu_hw_vdf_client PRIVATE ${VDF_COMMON_DEFINITIONS}) - target_include_directories(emu_hw_vdf_client PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/hw ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222) - target_link_libraries(emu_hw_vdf_client PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + add_executable(hw_vdf_client + ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_vdf_client.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/hw/real_hw.cpp + ) + target_sources(hw_vdf_client PRIVATE ${HW_COMMON_SOURCES} ${HW_VDF_ASM_SOURCES} ${VDF_COMMON_SOURCES}) + target_compile_definitions(hw_vdf_client PRIVATE ${VDF_COMMON_DEFINITIONS}) + target_include_directories(hw_vdf_client PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/hw ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222) + target_link_libraries(hw_vdf_client PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads ${HW_LIBS} ${HW_SOCKET_LIBS}) + if(APPLE) + target_link_options(hw_vdf_client PRIVATE "-Wl,-rpath,@executable_path/hw/libft4222") endif() + + add_executable(emu_hw_test + ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_test.cpp + ) + target_sources(emu_hw_test PRIVATE ${HW_COMMON_SOURCES} ${EMU_SOURCES} ${HW_VDF_ASM_SOURCES} ${VDF_COMMON_SOURCES}) + target_compile_definitions(emu_hw_test PRIVATE ${VDF_COMMON_DEFINITIONS}) + target_include_directories(emu_hw_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/hw ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222) + target_link_libraries(emu_hw_test PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads) + + add_executable(emu_hw_vdf_client + ${CMAKE_CURRENT_SOURCE_DIR}/hw/hw_vdf_client.cpp + ) + target_sources(emu_hw_vdf_client PRIVATE ${HW_COMMON_SOURCES} ${EMU_SOURCES} ${HW_VDF_ASM_SOURCES} ${VDF_COMMON_SOURCES}) + target_compile_definitions(emu_hw_vdf_client PRIVATE ${VDF_COMMON_DEFINITIONS}) + target_include_directories(emu_hw_vdf_client PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/hw ${CMAKE_CURRENT_SOURCE_DIR}/hw/libft4222) + target_link_libraries(emu_hw_vdf_client PRIVATE ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} Threads::Threads ${HW_SOCKET_LIBS}) endif() add_executable(verifier_test diff --git a/src/Makefile.vdf-client b/src/Makefile.vdf-client index 9b0aa5a5..8a7d7652 100644 --- a/src/Makefile.vdf-client +++ b/src/Makefile.vdf-client @@ -3,8 +3,14 @@ ARCH := $(shell uname -m) ifneq (,$(findstring clang, $(shell $(CXX) --version))) NOPIE = -fno-PIE +LTO_FLAGS = -flto else NOPIE = -no-pie +LTO_FLAGS = -flto=auto +endif +# Windows builds don't use PIE flags. +ifeq ($(OS),Windows_NT) +NOPIE = endif # macOS arm64 ignores -no_pie and warns; omit to avoid deprecation warnings ifeq ($(UNAME),Darwin) @@ -13,18 +19,26 @@ NOPIE = endif endif -LDFLAGS += -flto $(NOPIE) -g +CFLAGS += $(LTO_FLAGS) $(NOPIE) +LDFLAGS += $(LTO_FLAGS) $(NOPIE) -g +ifeq ($(OS),Windows_NT) +LDLIBS += -lmpirxx -lmpir -lws2_32 +CXXFLAGS += $(LTO_FLAGS) -std=c++1z -D VDF_MODE=0 -D FAST_MACHINE=1 $(NOPIE) -fvisibility=hidden +else LDLIBS += -lgmpxx -lgmp -pthread -CXXFLAGS += -flto -std=c++1z -D VDF_MODE=0 -D FAST_MACHINE=1 -pthread $(NOPIE) -fvisibility=hidden +CXXFLAGS += $(LTO_FLAGS) -std=c++1z -D VDF_MODE=0 -D FAST_MACHINE=1 -pthread $(NOPIE) -fvisibility=hidden +endif ifeq ($(UNAME),Darwin) CXXFLAGS += -D CHIAOSX=1 # Homebrew (common on macOS) installs boost/gmp to /opt/homebrew or /usr/local ifneq ($(wildcard /opt/homebrew/include/boost/asio.hpp),) CXXFLAGS += -I/opt/homebrew/include +CFLAGS += -I/opt/homebrew/include LDFLAGS += -L/opt/homebrew/lib endif ifneq ($(wildcard /usr/local/include/boost/asio.hpp),) CXXFLAGS += -I/usr/local/include +CFLAGS += -I/usr/local/include LDFLAGS += -L/usr/local/lib endif endif @@ -62,7 +76,7 @@ $(BINS) avx512_test: %: %.o lzcnt.o $(ASM_OBJS) $(addsuffix .o,$(BINS)) avx512_test.o: CXXFLAGS += $(OPT_CFLAGS) lzcnt.o: refcode/lzcnt.c - $(CC) -c refcode/lzcnt.c + $(CC) $(CFLAGS) -c refcode/lzcnt.c asm_compiled.s: compile_asm ./compile_asm @@ -76,17 +90,35 @@ avx512_asm_compiled.s: compile_asm compile_asm: compile_asm.o $(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS) -HW_OBJS = $(addprefix hw/,hw_util.o hw_proof.o hw_interface.o chia_driver.o ftdi_driver.o vdf_driver.o pll_freqs.o) vdf_base.o lzcnt.o +HW_OBJS = $(addprefix hw/,hw_util.o hw_proof.o hw_interface.o chia_driver.o ftdi_driver.o vdf_driver.o pll_freqs.o) vdf_base_hw.o vdf_hw_symbol_anchors.o lzcnt.o EMU_OBJS = hw/emu_funcs.o hw/emu_runner.o +ifeq ($(OS),Windows_NT) +HW_LIB = hw/libft4222/libft4222.lib +HW_FTD2XX_LIB = hw/libft4222/ftd2xx.lib +HW_LIBS = $(HW_LIB) $(HW_FTD2XX_LIB) +else +ifeq ($(UNAME),Darwin) +HW_LIB = hw/libft4222/libft4222.dylib +HW_FTD2XX_LIB = hw/libft4222/libftd2xx.dylib +HW_LIBS = $(HW_LIB) $(HW_FTD2XX_LIB) +else HW_LIB = hw/libft4222/build-x86_64/libft4222.so +HW_LIBS = $(HW_LIB) +endif +endif + +ifeq ($(UNAME),Darwin) +# Ensure HW client binaries can locate USB driver dylibs bundled in-tree. +hw_test hw_vdf_client: LDFLAGS += -Wl,-rpath,@executable_path/hw/libft4222 +endif -hw_test: hw/hw_test.o $(HW_OBJS) $(HW_LIB) hw/real_hw.o +hw_test: hw/hw_test.o $(HW_OBJS) $(HW_LIBS) hw/real_hw.o $(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS) emu_hw_test: hw/hw_test.o $(HW_OBJS) $(EMU_OBJS) $(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS) -hw_vdf_client: hw/hw_vdf_client.o $(HW_OBJS) $(HW_LIB) hw/real_hw.o +hw_vdf_client: hw/hw_vdf_client.o $(HW_OBJS) $(HW_LIBS) hw/real_hw.o $(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS) emu_hw_vdf_client: hw/hw_vdf_client.o $(HW_OBJS) $(EMU_OBJS) diff --git a/src/vdf_hw_symbol_anchors.cpp b/src/vdf_hw_symbol_anchors.cpp new file mode 100644 index 00000000..0ae53260 --- /dev/null +++ b/src/vdf_hw_symbol_anchors.cpp @@ -0,0 +1,24 @@ +#include "verifier.h" +#include "prover_base.hpp" +#include "prover_parallel.hpp" + +bool hw_dummy_form_check_valid(form& f, integer& d) +{ + return f.check_valid(d); +} + +form hw_dummy_get_proof(ParallelProver& p) +{ + p.GenerateProof(); + return p.GetProof(); +} + +void hw_dummy_verify_wesolowski(integer& D, form x, form y, form proof, uint64_t iters, bool& is_valid) +{ + VerifyWesolowskiProof(D, x, y, proof, iters, is_valid); +} + +integer hw_dummy_get_B(const integer& D, form& x, form& y) +{ + return GetB(D, x, y); +} From 9228710952fdcb0ca5667b424017f97a97fbb541 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Thu, 12 Feb 2026 13:25:58 -0800 Subject: [PATCH 50/78] core: reduce two-weso hot-path contention and fix Windows weak-symbol linkage. Move two-weso checkpoint state to safer synchronization semantics while preserving fast iteration paths, and disable weak-attribute usage on Windows to prevent duplicate lzcnt symbol failures. Co-authored-by: Cursor --- src/Reducer.h | 4 +++- src/callback.h | 52 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/Reducer.h b/src/Reducer.h index 913d747a..9fa7b5b5 100644 --- a/src/Reducer.h +++ b/src/Reducer.h @@ -29,7 +29,9 @@ limitations under the License. # define HAS_ATTRIBUTE(x) 0 #endif -#if HAS_ATTRIBUTE(weak) +#if defined(_WIN32) +# define WEAK +#elif HAS_ATTRIBUTE(weak) # define WEAK __attribute__((weak)) #else # define WEAK diff --git a/src/callback.h b/src/callback.h index 53c203ac..22e26f8c 100644 --- a/src/callback.h +++ b/src/callback.h @@ -131,27 +131,30 @@ class TwoWesolowskiCallback: public WesolowskiCallback { forms_capacity = space_needed; forms.reset(new form[space_needed]); forms[0] = f; - kl = 10; - switch_iters = -1; + kl.store(10, std::memory_order_relaxed); + switch_iters.store(-1, std::memory_order_relaxed); + switch_index.store(0, std::memory_order_relaxed); } void IncreaseConstants(uint64_t num_iters) { - std::lock_guard lk(forms_mutex); - kl = 100; - switch_iters = num_iters; - switch_index = num_iters / 10; + // Publish transition metadata first, then publish kl=100. + // OnIteration acquires kl before consuming switch state. + switch_index.store(num_iters / 10, std::memory_order_relaxed); + switch_iters.store(static_cast(num_iters), std::memory_order_relaxed); + kl.store(100, std::memory_order_release); } int GetPosition(uint64_t power) { - std::lock_guard lk(forms_mutex); return GetPositionUnlocked(power); } int GetPositionUnlocked(uint64_t power) const { - if (switch_iters == -1 || power < switch_iters) { + const int64_t current_switch_iters = switch_iters.load(std::memory_order_acquire); + if (current_switch_iters == -1 || power < static_cast(current_switch_iters)) { return power / 10; } else { - return (switch_index + (power - switch_iters) / 100); + const uint64_t current_switch_index = switch_index.load(std::memory_order_relaxed); + return static_cast(current_switch_index + (power - static_cast(current_switch_iters)) / 100); } } @@ -165,27 +168,34 @@ class TwoWesolowskiCallback: public WesolowskiCallback { } bool LargeConstants() { - std::lock_guard lk(forms_mutex); - return kl == 100; + return kl.load(std::memory_order_relaxed) == 100; } void OnIteration(int type, void *data, uint64_t iteration) { iteration++; + // Most iterations are not checkpoints. Avoid mutex lock/unlock on that hot path. + const uint32_t current_kl = kl.load(std::memory_order_relaxed); + if (iteration % current_kl != 0) { + return; + } + std::lock_guard lk(forms_mutex); - if (iteration % kl == 0) { - const int pos = GetPositionUnlocked(iteration); - if (pos < 0 || static_cast(pos) >= forms_capacity) { - throw std::runtime_error("TwoWesolowskiCallback::OnIteration out of bounds"); - } - form* mulf = &forms[static_cast(pos)]; - SetForm(type, data, mulf); + const uint32_t locked_kl = kl.load(std::memory_order_acquire); + if (iteration % locked_kl != 0) { + return; } + const int pos = GetPositionUnlocked(iteration); + if (pos < 0 || static_cast(pos) >= forms_capacity) { + throw std::runtime_error("TwoWesolowskiCallback::OnIteration out of bounds"); + } + form* mulf = &forms[static_cast(pos)]; + SetForm(type, data, mulf); } private: - uint64_t switch_index; - int64_t switch_iters; - uint32_t kl; + std::atomic switch_index{0}; + std::atomic switch_iters{-1}; + std::atomic kl{10}; std::mutex forms_mutex; }; From 79ec9d812807c4c67e801d401a6478061a8fa3ca Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Thu, 12 Feb 2026 13:26:05 -0800 Subject: [PATCH 51/78] hw-runtime: harden emulator and driver portability paths. Fix Windows-specific emulator and FTDI driver portability edge cases and unify utility behavior so HW runtime codepaths behave consistently across supported platforms. Co-authored-by: Cursor --- src/hw/emu_funcs.cpp | 13 +++++++++++++ src/hw/emu_runner.cpp | 37 +++++++++++++++++++++++++++++++------ src/hw/ftdi_driver.hpp | 6 +++++- src/hw/hw_util.cpp | 14 ++++++++++---- src/hw/hw_util.hpp | 11 +++++++++++ src/hw/vdf_driver.cpp | 12 ++++++------ 6 files changed, 76 insertions(+), 17 deletions(-) diff --git a/src/hw/emu_funcs.cpp b/src/hw/emu_funcs.cpp index 8f6cb0ca..bbb4e9a3 100644 --- a/src/hw/emu_funcs.cpp +++ b/src/hw/emu_funcs.cpp @@ -10,6 +10,19 @@ #include #include +#ifdef _WIN32 +// The vendor headers mark these APIs as dllimport; emulator builds provide +// local definitions, so drop import attributes for this translation unit. +#ifdef FTD2XX_API +#undef FTD2XX_API +#endif +#define FTD2XX_API +#ifdef LIBFT4222_API +#undef LIBFT4222_API +#endif +#define LIBFT4222_API +#endif + int chia_vdf_is_emu = 1; #define EMU_LOC_ID 0x88888 diff --git a/src/hw/emu_runner.cpp b/src/hw/emu_runner.cpp index 356365ac..4d04dae4 100644 --- a/src/hw/emu_runner.cpp +++ b/src/hw/emu_runner.cpp @@ -9,8 +9,24 @@ #include #include +#ifndef _WIN32 #include -#include +#endif + +#ifdef _WIN32 +static inline uint32_t bswap32_local(uint32_t x) +{ + return ((x & 0x000000FFu) << 24) | + ((x & 0x0000FF00u) << 8) | + ((x & 0x00FF0000u) >> 8) | + ((x & 0xFF000000u) >> 24); +} +static inline uint32_t htonl_local(uint32_t x) { return bswap32_local(x); } +static inline uint32_t ntohl_local(uint32_t x) { return bswap32_local(x); } +#else +static inline uint32_t htonl_local(uint32_t x) { return htonl(x); } +static inline uint32_t ntohl_local(uint32_t x) { return ntohl(x); } +#endif #define N_VDFS 3 @@ -92,7 +108,7 @@ void run_job(int i) reducer.reduce(qf2); if (!(st->cur_iter % 4096)) { - usleep(10); + vdf_usleep(10); } st->mtx.lock(); @@ -114,7 +130,7 @@ static void start_job(int i) while (states[i]->running) { states[i]->stopping = true; LOG_INFO("Emu %d: Waiting for the old thread to finish", i); - usleep(1000); + vdf_usleep(1000); } clear_state(states[i]); @@ -139,7 +155,11 @@ static void enable_engine(int i) states[i]->init_done = false; states[i]->stopping = true; states[i]->running = false; + #ifdef _WIN32 + srand(1); + #else srand48(1); + #endif } if (states[i]->stopping) { states[i]->stopping = false; @@ -155,7 +175,12 @@ void inject_error(struct job_status *stat, struct job_state *st) p = prob ? atoi(prob) : 0; g_error_prob = p; } - if (p != 0 && (st->error || (uint32_t)mrand48() % p == 0)) { + #ifdef _WIN32 + const uint32_t rand_val = static_cast(rand()); + #else + const uint32_t rand_val = static_cast(mrand48()); + #endif + if (p != 0 && (st->error || (rand_val % static_cast(p) == 0))) { // Inject error by messing up 'a' register stat->a[10] = ~stat->a[10]; st->error = true; @@ -269,7 +294,7 @@ int emu_do_io(uint8_t *buf_in, uint16_t size_in, uint8_t *buf_out, uint16_t size if (addr == job_control) { uint32_t data; memcpy(&data, buf_in, 4); - data = ntohl(data); + data = ntohl_local(data); if (data & (1U << CHIA_VDF_CONTROL_CLK_ENABLE_BIT)) { enable_engine(i); } else { @@ -287,7 +312,7 @@ int emu_do_io(uint8_t *buf_in, uint16_t size_in, uint8_t *buf_out, uint16_t size read_regs(addr, buf_out, size_out); } else if (!size_out && addr < sizeof(g_pll_regs)) { uint8_t *regs_addr = &((uint8_t *)g_pll_regs)[addr]; - uint32_t status_val = htonl((1U << CLOCK_STATUS_DIVACK_BIT) | + uint32_t status_val = htonl_local((1U << CLOCK_STATUS_DIVACK_BIT) | (1U << CLOCK_STATUS_LOCK_BIT)); copy_regs(regs_addr, buf_in, size_in, sizeof(g_pll_regs) - addr, 0); diff --git a/src/hw/ftdi_driver.hpp b/src/hw/ftdi_driver.hpp index e740c9fd..ad749288 100644 --- a/src/hw/ftdi_driver.hpp +++ b/src/hw/ftdi_driver.hpp @@ -13,7 +13,11 @@ void print_buf(size_t offset, uint8_t *buf, size_t size); class FtdiDriver { public: - typedef unsigned int DWORD; +#ifdef _WIN32 + using DWORD = ::DWORD; +#else + using DWORD = unsigned int; +#endif static const unsigned GPIO2 = 2; static const unsigned GPIO3 = 3; diff --git a/src/hw/hw_util.cpp b/src/hw/hw_util.cpp index 77f7f7c2..a68ed474 100644 --- a/src/hw/hw_util.cpp +++ b/src/hw/hw_util.cpp @@ -8,12 +8,18 @@ void vdf_do_log(const char *msg, ...) va_list ap; struct tm cal; char time_str[25]; - struct timespec ts; + auto now = std::chrono::system_clock::now(); + auto secs = std::chrono::time_point_cast(now); + auto millis = std::chrono::duration_cast(now - secs).count(); + std::time_t tt = std::chrono::system_clock::to_time_t(now); - clock_gettime(CLOCK_REALTIME, &ts); - localtime_r(&ts.tv_sec, &cal); +#ifdef _WIN32 + localtime_s(&cal, &tt); +#else + localtime_r(&tt, &cal); +#endif strftime(time_str, sizeof(time_str), "%FT%T", &cal); - fprintf(stderr, "%s.%03ld ", time_str, ts.tv_nsec / 1000000); + fprintf(stderr, "%s.%03lld ", time_str, static_cast(millis)); va_start(ap, msg); vfprintf(stderr, msg, ap); diff --git a/src/hw/hw_util.hpp b/src/hw/hw_util.hpp index bb2c7805..daa05a54 100644 --- a/src/hw/hw_util.hpp +++ b/src/hw/hw_util.hpp @@ -3,6 +3,7 @@ #include #include +#include void vdf_do_log(const char *msg, ...); @@ -33,4 +34,14 @@ static inline uint64_t vdf_get_elapsed_us(timepoint_t &t1) return std::chrono::duration_cast(t2 - t1).count(); } +static inline void vdf_usleep(uint64_t usec) +{ + std::this_thread::sleep_for(std::chrono::microseconds(usec)); +} + +static inline void vdf_sleep(uint64_t sec) +{ + std::this_thread::sleep_for(std::chrono::seconds(sec)); +} + #endif /* HW_UTIL_H */ diff --git a/src/hw/vdf_driver.cpp b/src/hw/vdf_driver.cpp index 15109165..9709b200 100644 --- a/src/hw/vdf_driver.cpp +++ b/src/hw/vdf_driver.cpp @@ -2,9 +2,9 @@ #include #include #include -#include #include "vdf_driver.hpp" #include "pll_freqs.hpp" +#include "hw_util.hpp" #define VR_I2C_ADDR 0x38 #define CS_I2C_ADDR 0x70 @@ -372,7 +372,7 @@ bool VdfDriver::SetPLLFrequency(double frequency, uint32_t entry_index) { while (((pll_status >> CLOCK_STATUS_DIVACK_BIT) & 0x1) == 0) { ret_val = RegRead(CLOCK_STATUS_REG_OFFSET, pll_status); read_attempts++; - usleep(1000); + vdf_usleep(1000); if ((read_attempts > 4) || (ret_val != 0)) { fprintf(stderr, "SetPLLFrequency pll div never ack'd\n"); return false; @@ -388,7 +388,7 @@ bool VdfDriver::SetPLLFrequency(double frequency, uint32_t entry_index) { while (((pll_status >> CLOCK_STATUS_LOCK_BIT) & 0x1) == 0) { ret_val = RegRead(CLOCK_STATUS_REG_OFFSET, pll_status); read_attempts++; - usleep(1000); + vdf_usleep(1000); if ((read_attempts > 4) || (ret_val != 0)) { fprintf(stderr, "SetPLLFrequency pll never locked\n"); return false; @@ -449,7 +449,7 @@ int VdfDriver::Reset(uint32_t sleep_duration = 1000) { fprintf(stderr, "Reset failed to set gpio, %d\n", ret_val); return ret_val; } - usleep(sleep_duration); + vdf_usleep(sleep_duration); // Some boards will contain FT4222H chips with the OTP programmed such // that GPIO2 (VDF_RST_N) is configured as an open drain output. In // this case, GPIO2 powers up actively driving out low. In order to @@ -479,7 +479,7 @@ int VdfDriver::Reset(uint32_t sleep_duration = 1000) { if (ret_val != 0) { fprintf(stderr, "Reset failed to tri-state gpio, %d\n", ret_val); } - usleep(100000); + vdf_usleep(100000); return ret_val; } @@ -604,7 +604,7 @@ double VdfDriver::GetBoardCurrent() { return 0.0; } - usleep(10000); + vdf_usleep(10000); ret_val = I2CReadReg(CS_I2C_ADDR, 0x0, 2, (uint8_t*)(&cs)); if (ret_val != 0) { From 059b441b72895e3b8af41bf4bae9d5ecef27e1ec Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Thu, 12 Feb 2026 13:26:11 -0800 Subject: [PATCH 52/78] hw-tools: stabilize client, proof, and test integration on Windows. Correct HW interface/proof/test interactions and client loop behavior so Windows hardware tooling builds and runs with the same semantics as other platforms. Co-authored-by: Cursor --- src/hw/hw_interface.cpp | 1 - src/hw/hw_proof.cpp | 7 +-- src/hw/hw_test.cpp | 4 +- src/hw/hw_vdf_client.cpp | 120 +++++++++++++++++++++++++++++++-------- src/vdf_base_hw.cpp | 10 ++++ 5 files changed, 109 insertions(+), 33 deletions(-) create mode 100644 src/vdf_base_hw.cpp diff --git a/src/hw/hw_interface.cpp b/src/hw/hw_interface.cpp index d3cbf66f..129c6c63 100644 --- a/src/hw/hw_interface.cpp +++ b/src/hw/hw_interface.cpp @@ -9,7 +9,6 @@ #include #include -#include #define REG_BYTES 4 #define CHIA_VDF_JOB_SIZE (CHIA_VDF_CMD_START_REG_OFFSET - \ diff --git a/src/hw/hw_proof.cpp b/src/hw/hw_proof.cpp index 3ea63ee6..593f6042 100644 --- a/src/hw/hw_proof.cpp +++ b/src/hw/hw_proof.cpp @@ -4,7 +4,6 @@ #include #include -#include static const uint32_t g_chkp_thres = 1000000; static const uint32_t g_skip_thres = 10; @@ -474,13 +473,13 @@ void hw_proof_wait_values(struct vdf_state *vdf, bool finish_work) { if (finish_work) { while (!vdf->wq.empty()) { - usleep(100000); + vdf_usleep(100000); hw_proof_process_work(vdf); } } while (vdf->aux_threads_busy) { - usleep(10000); + vdf_usleep(10000); } if (!finish_work) { @@ -495,7 +494,7 @@ void hw_proof_wait_values(struct vdf_state *vdf, bool finish_work) int hw_proof_wait_value(struct vdf_state *vdf, size_t pos) { while (!(vdf->valid_values[pos / 8] & (1 << (pos % 8)))) { - usleep(100000); + vdf_usleep(100000); if (vdf->stopping) { return -1; } diff --git a/src/hw/hw_test.cpp b/src/hw/hw_test.cpp index 20df7694..4509a1ab 100644 --- a/src/hw/hw_test.cpp +++ b/src/hw/hw_test.cpp @@ -19,8 +19,6 @@ #include #include -#include - static const char *discrs[] = { "-0xac566497f63870a7b661f5482f47336cd1aa85ab43914828b7998f255916729c2ad965bcf7fe231721d96706ea7d823ed4adf663a0263714bb80144aebafcdd2915b6c7ef68c2d19447be83e7f39b4a7442640914053d2e7d6a561aa29b9449c815717af7da97a823798f402d073901a1f2bd8cd879b8b1afe2496649197021f", "-0xc3657f850b3f2b659d70273704564bc69b849fe1d8c70b096933efdcf7143931b393676f500d79624da783d73e0c5303ae48fb9543502c4161586d8fdaf03709d2115df21aeeee4a58614050cbdfe74024063b9620de084d8ef46f474fa57983c4bebfa7e8a69efeb523a167558fe1487a086c11337e20b773ad3d4710671417", @@ -100,7 +98,7 @@ int hw_test_main(int argc, char **argv) //break; //} if (chia_vdf_is_emu) { - usleep(50000); + vdf_usleep(50000); } read_cnt++; } diff --git a/src/hw/hw_vdf_client.cpp b/src/hw/hw_vdf_client.cpp index 19d063dd..3e873c94 100644 --- a/src/hw/hw_vdf_client.cpp +++ b/src/hw/hw_vdf_client.cpp @@ -6,15 +6,25 @@ #include "chia_driver.hpp" #include "pll_freqs.hpp" -#include #include -#include #include #include + +#ifdef _WIN32 +#include +#include +using vdf_socket_t = SOCKET; +static constexpr vdf_socket_t kInvalidSocket = INVALID_SOCKET; +#else +#include +#include #include #include #include #include +using vdf_socket_t = int; +static constexpr vdf_socket_t kInvalidSocket = -1; +#endif enum conn_state { WAITING, @@ -26,7 +36,7 @@ enum conn_state { struct vdf_conn { struct vdf_state vdf; - int sock; + vdf_socket_t sock; char read_buf[512]; uint32_t buf_pos; enum conn_state state; @@ -63,6 +73,52 @@ void write_data(struct vdf_conn *conn, const char *buf, size_t size); static volatile bool g_stopping = false; +static int vdf_socket_set_nonblock(vdf_socket_t sock) +{ +#ifdef _WIN32 + u_long mode = 1; + return ioctlsocket(sock, FIONBIO, &mode); +#else + return fcntl(sock, F_SETFL, O_NONBLOCK); +#endif +} + +static int vdf_socket_read(vdf_socket_t sock, char *buf, size_t size) +{ +#ifdef _WIN32 + return recv(sock, buf, static_cast(size), 0); +#else + return read(sock, buf, size); +#endif +} + +static int vdf_socket_write(vdf_socket_t sock, const char *buf, size_t size) +{ +#ifdef _WIN32 + return send(sock, buf, static_cast(size), 0); +#else + return write(sock, buf, size); +#endif +} + +static int vdf_socket_close(vdf_socket_t sock) +{ +#ifdef _WIN32 + return closesocket(sock); +#else + return close(sock); +#endif +} + +static bool vdf_socket_would_block() +{ +#ifdef _WIN32 + return WSAGetLastError() == WSAEWOULDBLOCK; +#else + return errno == EAGAIN || errno == EWOULDBLOCK; +#endif +} + void signal_handler(int sig) { LOG_INFO("Interrupted"); @@ -72,21 +128,24 @@ void signal_handler(int sig) void init_conn(struct vdf_conn *conn, uint32_t ip, int port) { int ret; - struct sockaddr_in sa = { AF_INET, htons(port), { htonl(ip) } }; + struct sockaddr_in sa = {}; + sa.sin_family = AF_INET; + sa.sin_port = htons(static_cast(port)); + sa.sin_addr.s_addr = htonl(ip); conn->sock = socket(AF_INET, SOCK_STREAM, 0); LOG_INFO("Connecting to %s:%d", inet_ntoa(sa.sin_addr), port); ret = connect(conn->sock, (struct sockaddr *)&sa, sizeof(sa)); if (ret < 0) { perror("connect"); - sleep(1); + vdf_sleep(1); return; } - ret = fcntl(conn->sock, F_SETFL, O_NONBLOCK); + ret = vdf_socket_set_nonblock(conn->sock); if (ret < 0) { - perror("fcntl"); - close(conn->sock); - conn->sock = -1; + perror("set_nonblock"); + vdf_socket_close(conn->sock); + conn->sock = kInvalidSocket; return; } conn->state = WAITING; @@ -126,7 +185,7 @@ void clear_vdf_client(struct vdf_client *client) void stop_conn(struct vdf_client *client, struct vdf_conn *conn) { - if (conn->sock >= 0) { + if (conn->sock != kInvalidSocket) { write_data(conn, "STOP", 4); } if (conn->vdf.init_done) { @@ -135,24 +194,24 @@ void stop_conn(struct vdf_client *client, struct vdf_conn *conn) stop_hw_vdf(client->drv, conn->vdf.idx); } conn->state = STOPPED; - LOG_INFO("VDF %d: Stopped at iters=%lu", conn->vdf.idx, conn->vdf.cur_iters); + LOG_INFO("VDF %d: Stopped at iters=%llu", conn->vdf.idx, (unsigned long long)conn->vdf.cur_iters); } void close_conn(struct vdf_conn *conn) { if (conn->state != CLOSED) { - close(conn->sock); - conn->sock = -1; + vdf_socket_close(conn->sock); + conn->sock = kInvalidSocket; conn->state = CLOSED; LOG_INFO("VDF %d: Connection closed", conn->vdf.idx); } } -ssize_t read_data(struct vdf_client *client, struct vdf_conn *conn) +int read_data(struct vdf_client *client, struct vdf_conn *conn) { - ssize_t bytes = read(conn->sock, conn->read_buf + conn->buf_pos, + int bytes = vdf_socket_read(conn->sock, conn->read_buf + conn->buf_pos, sizeof(conn->read_buf) - conn->buf_pos); - if ((bytes < 0 && errno != EAGAIN) || bytes == 0) { + if ((bytes < 0 && !vdf_socket_would_block()) || bytes == 0) { if (bytes == 0) { LOG_ERROR("VDF %d: Unexpected EOF", conn->vdf.idx); } else { @@ -169,7 +228,7 @@ ssize_t read_data(struct vdf_client *client, struct vdf_conn *conn) void write_data(struct vdf_conn *conn, const char *buf, size_t size) { - ssize_t bytes = write(conn->sock, buf, size); + int bytes = vdf_socket_write(conn->sock, buf, size); if (bytes < 0) { perror("write"); throw std::runtime_error("Write error"); @@ -196,7 +255,7 @@ void handle_iters(struct vdf_client *client, struct vdf_conn *conn) iters = strtoul(iters_buf, NULL, 10); if (iters) { - LOG_DEBUG("VDF %d: Requested proof for iters=%lu", conn->vdf.idx, iters); + LOG_DEBUG("VDF %d: Requested proof for iters=%llu", conn->vdf.idx, (unsigned long long)iters); hw_request_proof(&conn->vdf, iters, false); } else { LOG_INFO("VDF %d: Stop requested", conn->vdf.idx); @@ -217,8 +276,8 @@ void handle_iters(struct vdf_client *client, struct vdf_conn *conn) size_t pos = 0; for (size_t i = 0; i < n_proofs; i++) { - pos += snprintf(&iters_str[pos], sizeof(iters_str) - pos, "%s%lu", - i ? ", " : "", conn->vdf.req_proofs[i].iters); + pos += snprintf(&iters_str[pos], sizeof(iters_str) - pos, "%s%llu", + i ? ", " : "", (unsigned long long)conn->vdf.req_proofs[i].iters); if (pos >= sizeof(iters_str) - 1) { break; } @@ -243,7 +302,7 @@ void handle_proofs(struct vdf_client *client, struct vdf_conn *conn) uint8_t data[8 + 8 + 1 + BQFC_FORM_SIZE * 2]; char tl_data[sizeof(data) * 2 + 5] = {0}; - LOG_INFO("VDF %d: Proof retrieved for iters=%lu", conn->vdf.idx, proof->iters); + LOG_INFO("VDF %d: Proof retrieved for iters=%llu", conn->vdf.idx, (unsigned long long)proof->iters); Int64ToBytes(&data[0], proof->iters); Int64ToBytes(&data[8], BQFC_FORM_SIZE); @@ -272,7 +331,7 @@ void handle_proofs(struct vdf_client *client, struct vdf_conn *conn) void handle_conn(struct vdf_client *client, struct vdf_conn *conn) { - ssize_t bytes; + int bytes; char *buf = conn->read_buf; struct vdf_state *vdf = &conn->vdf; @@ -386,8 +445,8 @@ void event_loop(struct vdf_client *client) adjust_hw_freq(client->drv, running_mask & ~(1 << i), -1); } - LOG_INFO("VDF %d: Restarting VDF at %lu iters", - vdf->idx, vdf->iters_offset); + LOG_INFO("VDF %d: Restarting VDF at %llu iters", + vdf->idx, (unsigned long long)vdf->iters_offset); start_hw_vdf(client->drv, vdf->D.impl, f->a.impl, f->b.impl, vdf->target_iters - vdf->iters_offset, vdf->idx); } @@ -413,7 +472,7 @@ void event_loop(struct vdf_client *client) } if (chia_vdf_is_emu) { - usleep(50000); + vdf_usleep(50000); } loop_cnt++; } @@ -531,6 +590,14 @@ int hw_vdf_client_main(int argc, char **argv) struct vdf_client client; struct sigaction sa = {0}; +#ifdef _WIN32 + WSADATA wsa_data; + if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) { + LOG_SIMPLE("Failed to initialize Winsock"); + return 1; + } +#endif + if (parse_opts(argc, argv, &client.opts) < 0) { LOG_SIMPLE("\nUsage: %s [OPTIONS] PORT [N_VDFS]\n" "List of options [default, min - max]:\n" @@ -566,6 +633,9 @@ int hw_vdf_client_main(int argc, char **argv) stop_hw(client.drv); clear_vdf_client(&client); +#ifdef _WIN32 + WSACleanup(); +#endif return 0; } diff --git a/src/vdf_base_hw.cpp b/src/vdf_base_hw.cpp new file mode 100644 index 00000000..3f2a82af --- /dev/null +++ b/src/vdf_base_hw.cpp @@ -0,0 +1,10 @@ +#include "vdf_base.hpp" +#include "alloc.hpp" + +#include + +void VdfBaseInit(void) +{ + init_gmp(); + fesetround(FE_TOWARDZERO); +} From 0a1e1cf04688b407bfdd53e3fbbc19f55d0af8e3 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Thu, 12 Feb 2026 13:26:17 -0800 Subject: [PATCH 53/78] core: apply low-level portability cleanup for allocation and bqfc codepaths. Carry forward allocator initialization and bqfc portability fixes needed to keep non-Linux builds stable under the updated HW/runtime integration. Co-authored-by: Cursor --- src/alloc.hpp | 1 - src/bqfc.c | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/alloc.hpp b/src/alloc.hpp index a53d9f0c..f18377e7 100644 --- a/src/alloc.hpp +++ b/src/alloc.hpp @@ -52,7 +52,6 @@ inline void* mp_realloc_func(void* old_ptr, size_t old_size, size_t new_bytes) { //(the mpz class constructor does not call any gmp functions) inline void init_gmp() { mp_set_memory_functions(mp_alloc_func, mp_realloc_func, mp_free_func); - allow_integer_constructor=true; //make sure the old gmp allocator isn't used } #endif diff --git a/src/bqfc.c b/src/bqfc.c index 7e3ae35e..7d5782e6 100644 --- a/src/bqfc.c +++ b/src/bqfc.c @@ -3,6 +3,9 @@ #include #include +/* xgcd_partial.c is linked via C++ translation units; declare symbol for C++ compile path. */ +void mpz_xgcd_partial(mpz_t co2, mpz_t co1, mpz_t r2, mpz_t r1, const mpz_t L); + int bqfc_compr(struct qfb_c *out_c, mpz_t a, mpz_t b) { mpz_t a_sqrt, a_copy, b_copy, dummy; From b040ec1d43fc2ce9dc3c54fb0948d47222cd2670 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Thu, 12 Feb 2026 13:31:40 -0800 Subject: [PATCH 54/78] hw-client: fix bytes log format specifiers. Use `%d` for `bytes` in `handle_conn` so varargs types match the `int` return from `read_data`, avoiding LP64 UB from `%zd`. Co-authored-by: Cursor --- src/hw/hw_vdf_client.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hw/hw_vdf_client.cpp b/src/hw/hw_vdf_client.cpp index 3e873c94..0eb5f80b 100644 --- a/src/hw/hw_vdf_client.cpp +++ b/src/hw/hw_vdf_client.cpp @@ -364,7 +364,7 @@ void handle_conn(struct vdf_client *client, struct vdf_conn *conn) memcpy(d_str, &buf[4], d_size); d_str[d_size] = '\0'; if ((uint64_t)bytes != 4 + d_size + 1 + buf[4 + d_size]) { - LOG_ERROR("Bad data size: %zd", bytes); + LOG_ERROR("Bad data size: %d", bytes); throw std::runtime_error("Bad data size"); } @@ -388,7 +388,7 @@ void handle_conn(struct vdf_client *client, struct vdf_conn *conn) if (conn->state == STOPPED) { bytes = read_data(client, conn); if (bytes != 3 || memcmp(buf, "ACK", 3)) { - LOG_ERROR("Bad data size after stop: %zd", bytes); + LOG_ERROR("Bad data size after stop: %d", bytes); } close_conn(conn); } else if (conn->state == CLOSED && !g_stopping) { From 4e0745e1158adc75d4c56aa932763c5fae4d0de0 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Thu, 12 Feb 2026 13:33:41 -0800 Subject: [PATCH 55/78] hw-client: initialize sock with kInvalidSocket. Use the shared socket sentinel in init_vdf_client to avoid implicit signed-to-unsigned conversion on Windows SOCKET and keep socket state checks consistent. Co-authored-by: Cursor --- src/hw/hw_vdf_client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hw/hw_vdf_client.cpp b/src/hw/hw_vdf_client.cpp index 0eb5f80b..e6fc3515 100644 --- a/src/hw/hw_vdf_client.cpp +++ b/src/hw/hw_vdf_client.cpp @@ -166,7 +166,7 @@ void init_vdf_client(struct vdf_client *client) continue; } client->conns[i].vdf.idx = i; - client->conns[i].sock = -1; + client->conns[i].sock = kInvalidSocket; memset(client->conns[i].read_buf, 0, sizeof(client->conns[i].read_buf)); client->conns[i].buf_pos = 0; From 7220cacc97b39225283a1914453b8a67cd9b76f2 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 13 Feb 2026 11:46:20 -0800 Subject: [PATCH 56/78] hw-build: fix HW smoke regressions after main merge. Restore pre-merge asm/AVX runtime behavior to avoid emu_hw_test segfaults on Ubuntu, and harden Windows smoke-test PowerShell handling to fail only on real nonzero native exit codes. Co-authored-by: Cursor --- .github/workflows/hw-build.yml | 3 ++ src/asm_base.h | 12 -------- src/asm_gcd_unsigned.h | 22 +-------------- src/parameters.h | 51 +++------------------------------- 4 files changed, 8 insertions(+), 80 deletions(-) diff --git a/.github/workflows/hw-build.yml b/.github/workflows/hw-build.yml index 34a5265b..31a95ae2 100644 --- a/.github/workflows/hw-build.yml +++ b/.github/workflows/hw-build.yml @@ -231,6 +231,8 @@ jobs: working-directory: "${{ github.workspace }}/build" shell: pwsh run: | + # Keep native stderr as log output; emu binaries log diagnostics there. + $PSNativeCommandUseErrorActionPreference = $false $dllPaths = @() if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } if (Test-Path "$env:GITHUB_WORKSPACE\src\hw\libft4222") { $dllPaths += "$env:GITHUB_WORKSPACE\src\hw\libft4222" } @@ -238,6 +240,7 @@ jobs: if (Test-Path ".\hw_test.exe") { Write-Host "hw_test.exe present" } Write-Host "Running emu_hw_test" .\emu_hw_test.exe 1 2000 + if ($LASTEXITCODE -ne 0) { throw "emu_hw_test failed with exit code $LASTEXITCODE" } Write-Host "emu_hw_test completed" - name: Upload Artifacts diff --git a/src/asm_base.h b/src/asm_base.h index 601c8a9e..a1257925 100644 --- a/src/asm_base.h +++ b/src/asm_base.h @@ -79,29 +79,17 @@ string track_asm(string comment, string jump_to = "") { assert(!enable_threads); //this code isn't atomic - #if defined(CHIAOSX) || defined(CHIA_WINDOWS) APPEND_M(str( "MOV [RIP+track_asm_rax], RAX" )); APPEND_M(str( "MOV RAX, [RIP+asm_tracking_data+#]", to_hex(8*(id-1)) )); APPEND_M(str( "LEA RAX, [RAX+1]" )); APPEND_M(str( "MOV [RIP+asm_tracking_data+#], RAX", to_hex(8*(id-1)) )); - #else - APPEND_M(str( "MOV [track_asm_rax], RAX" )); - APPEND_M(str( "MOV RAX, [asm_tracking_data+#]", to_hex(8*(id-1)) )); - APPEND_M(str( "LEA RAX, [RAX+1]" )); - APPEND_M(str( "MOV [asm_tracking_data+#], RAX", to_hex(8*(id-1)) )); - #endif #if defined(CHIAOSX) || defined(CHIA_WINDOWS) APPEND_M(str( "LEA RAX, [RIP+#] ", comment_label )); #else APPEND_M(str( "MOV RAX, OFFSET FLAT:#", comment_label )); #endif - #if defined(CHIAOSX) || defined(CHIA_WINDOWS) APPEND_M(str( "MOV [RIP+asm_tracking_data_comments+#], RAX", to_hex(8*(id-1)) )); APPEND_M(str( "MOV RAX, [RIP+track_asm_rax]" )); - #else - APPEND_M(str( "MOV [asm_tracking_data_comments+#], RAX", to_hex(8*(id-1)) )); - APPEND_M(str( "MOV RAX, [track_asm_rax]" )); - #endif if (!jump_to.empty()) { APPEND_M(str( "JMP #", jump_to )); diff --git a/src/asm_gcd_unsigned.h b/src/asm_gcd_unsigned.h index 53c54cd1..f6bc1019 100644 --- a/src/asm_gcd_unsigned.h +++ b/src/asm_gcd_unsigned.h @@ -452,27 +452,7 @@ void gcd_unsigned( APPEND_M(str( ".balign 8" )); APPEND_M(str( "#:", jump_table_label )); -#if defined(CHIA_WINDOWS) - APPEND_M(str( ".text" )); - - string bad_end_index_label = track_asm( "gcd_unsigned invalid a_end_index", m.alloc_error_label() ); - APPEND_M(str( "MOV `tmp, `spill_a_end_index" )); - APPEND_M(str( "CMP `tmp, #", to_hex(int_size-1) )); - APPEND_M(str( "JA #", bad_end_index_label )); - - for (int end_index=0;end_index #include #include -#include #include -#if defined(_MSC_VER) -#include -#endif inline std::atomic bAVX2{false}; inline std::atomic enable_avx512_ifma{false}; @@ -86,18 +82,10 @@ inline void init_avx_flags() const bool enable_avx512 = env_flag("CHIA_ENABLE_AVX512_IFMA"); const bool force_avx512 = env_flag("CHIA_FORCE_AVX512_IFMA"); int info[4] = {0}; - int info1[4] = {0}; #if defined(_MSC_VER) - __cpuid(info1, 0x1); __cpuid(info, 0x7); #elif defined(__GNUC__) || defined(__clang__) #if defined(ARCH_X86) && defined(__PIC__) - __asm__ __volatile__ ( - "xchg{l} {%%}ebx, %k1;" - "cpuid;" - "xchg{l} {%%}ebx, %k1;" - : "=a"(info1[0]), "=&r"(info1[1]), "=c"(info1[2]), "=d"(info1[3]) : "a"(0x1), "c"(0) - ); __asm__ __volatile__ ( "xchg{l} {%%}ebx, %k1;" "cpuid;" @@ -105,9 +93,6 @@ inline void init_avx_flags() : "=a"(info[0]), "=&r"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(0x7), "c"(0) ); #else - __asm__ __volatile__ ( - "cpuid" : "=a"(info1[0]), "=b"(info1[1]), "=c"(info1[2]), "=d"(info1[3]) : "a"(0x1), "c"(0) - ); __asm__ __volatile__ ( "cpuid" : "=a"(info[0]), "=b"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(0x7), "c"(0) ); @@ -117,49 +102,21 @@ inline void init_avx_flags() const int ADX = 1<<19; const int AVX512F = 1<<16; const int AVX512IFMA = 1<<21; - const int XSAVE = 1<<26; - const int OSXSAVE = 1<<27; - const int AVX = 1<<28; bool avx2bit = ((info[1] & AVX2) == AVX2); bool adxbit = ((info[1] & ADX) == ADX); bool avx512fbit = ((info[1] & AVX512F) == AVX512F); bool avx512ifmabit = ((info[1] & AVX512IFMA) == AVX512IFMA); - bool xsavebit = ((info1[2] & XSAVE) == XSAVE); - bool osxsavebit = ((info1[2] & OSXSAVE) == OSXSAVE); - bool avxbit = ((info1[2] & AVX) == AVX); - bool os_avx2_state = false; - bool os_avx512_state = false; - if (xsavebit && osxsavebit) { -#if defined(_MSC_VER) - unsigned long long xcr0 = _xgetbv(0); -#elif defined(__GNUC__) || defined(__clang__) - uint32_t eax = 0; - uint32_t edx = 0; - __asm__ __volatile__ ( - ".byte 0x0f, 0x01, 0xd0" - : "=a"(eax), "=d"(edx) - : "c"(0) - ); - uint64_t xcr0 = (uint64_t(eax) | (uint64_t(edx) << 32)); -#else - uint64_t xcr0 = 0; -#endif - const uint64_t xcr0_avx = (uint64_t(1) << 1) | (uint64_t(1) << 2); - const uint64_t xcr0_avx512 = xcr0_avx | (uint64_t(1) << 5) | (uint64_t(1) << 6) | (uint64_t(1) << 7); - os_avx2_state = (xcr0 & xcr0_avx) == xcr0_avx; - os_avx512_state = (xcr0 & xcr0_avx512) == xcr0_avx512; - } if (disable_avx2) { bAVX2.store(false, std::memory_order_relaxed); } else if (force_avx2) { bAVX2.store(true, std::memory_order_relaxed); } else { - bAVX2.store(avx2bit && adxbit && avxbit && os_avx2_state, std::memory_order_relaxed); + bAVX2.store(avx2bit && adxbit, std::memory_order_relaxed); } if (bAVX2.load(std::memory_order_relaxed) && should_log_avx()) { - std::fprintf(stderr, "AVX2 enabled (avx2=%d adx=%d avx=%d os_avx2=%d)\n", avx2bit ? 1 : 0, adxbit ? 1 : 0, avxbit ? 1 : 0, os_avx2_state ? 1 : 0); + std::fprintf(stderr, "AVX2 enabled (avx2=%d adx=%d)\n", avx2bit ? 1 : 0, adxbit ? 1 : 0); } if (disable_avx512) { @@ -167,12 +124,12 @@ inline void init_avx_flags() } else if (force_avx512) { enable_avx512_ifma.store(true, std::memory_order_relaxed); } else if (enable_avx512) { - enable_avx512_ifma.store(avx512fbit && avx512ifmabit && avxbit && os_avx512_state, std::memory_order_relaxed); + enable_avx512_ifma.store(avx512fbit && avx512ifmabit, std::memory_order_relaxed); } else { enable_avx512_ifma.store(false, std::memory_order_relaxed); } if (enable_avx512_ifma.load(std::memory_order_relaxed) && should_log_avx()) { - std::fprintf(stderr, "AVX512 IFMA enabled (f=%d ifma=%d avx=%d os_avx512=%d)\n", avx512fbit ? 1 : 0, avx512ifmabit ? 1 : 0, avxbit ? 1 : 0, os_avx512_state ? 1 : 0); + std::fprintf(stderr, "AVX512 IFMA enabled (f=%d ifma=%d)\n", avx512fbit ? 1 : 0, avx512ifmabit ? 1 : 0); } #elif defined(ARCH_ARM) bAVX2.store(false, std::memory_order_relaxed); From 6be75ad11b74c496ca34cf2e4a20f1aba40d53cb Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 13 Feb 2026 12:01:43 -0800 Subject: [PATCH 57/78] hw-proof: align Prover GetForm ABI across prover stacks. Restore pointer-based GetForm signatures and call sites in prover_base/prover_parallel/provers to match vdf_base.hpp, eliminating mixed class ABI definitions that can cause emu_hw_test crashes. Co-authored-by: Cursor --- src/prover_base.hpp | 6 +++--- src/prover_parallel.hpp | 4 ++-- src/provers.h | 14 ++++++++------ 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/prover_base.hpp b/src/prover_base.hpp index 659718d9..fb2678da 100644 --- a/src/prover_base.hpp +++ b/src/prover_base.hpp @@ -16,7 +16,7 @@ class Prover { is_finished = false; } - virtual form GetForm(uint64_t iteration) = 0; + virtual form* GetForm(uint64_t iteration) = 0; virtual void start() = 0; virtual void stop() = 0; virtual bool PerformExtraStep() = 0; @@ -76,8 +76,8 @@ class Prover { throw std::runtime_error("GenerateProof block index out of bounds"); } if (!PerformExtraStep()) return; - form tmp = GetForm(i); - nucomp_form(ys[b], ys[b], tmp, D, L); + form* tmp = GetForm(i); + nucomp_form(ys[b], ys[b], *tmp, D, L); } } diff --git a/src/prover_parallel.hpp b/src/prover_parallel.hpp index a14120bf..2f0fde7d 100644 --- a/src/prover_parallel.hpp +++ b/src/prover_parallel.hpp @@ -45,8 +45,8 @@ class ParallelProver : public Prover { if (num_iterations >= k * (i * l + j + 1)) { uint64_t b = GetBlock(i*l + j, k, num_iterations, B); if (!PerformExtraStep()) return; - form tmp = GetForm(i); - nucomp_form(ys[b], ys[b], tmp, D, L); + form* tmp = GetForm(i); + nucomp_form(ys[b], ys[b], *tmp, D, L); } } diff --git a/src/provers.h b/src/provers.h index ffb12450..8d8437bb 100644 --- a/src/provers.h +++ b/src/provers.h @@ -18,8 +18,8 @@ class OneWesolowskiProver : public Prover { } } - form GetForm(uint64_t iteration) { - return intermediates[iteration]; + form* GetForm(uint64_t iteration) { + return &intermediates[iteration]; } void start() { @@ -72,9 +72,10 @@ class TwoWesolowskiProver : public Prover{ } } - virtual form GetForm(uint64_t i) { + virtual form* GetForm(uint64_t i) { const uint64_t power = done_iterations + i * k * l; - return weso->GetFormCopy(power); + cached_form = weso->GetFormCopy(power); + return &cached_form; } void stop() { @@ -95,6 +96,7 @@ class TwoWesolowskiProver : public Prover{ TwoWesolowskiCallback* weso; std::atomic& stop_signal; uint64_t done_iterations; + form cached_form; std::thread worker; }; @@ -128,8 +130,8 @@ class InterruptableProver: public Prover { delete(th); } - form GetForm(uint64_t i) { - return *weso->GetForm(done_iterations + i * k * l, bucket); + form* GetForm(uint64_t i) { + return weso->GetForm(done_iterations + i * k * l, bucket); } void start() { From 74974506a68c8c940621f571858aef1dbc42ab0d Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 13 Feb 2026 12:42:27 -0800 Subject: [PATCH 58/78] callback: restore one-weso bounds guard in iteration callback. Reinstate explicit bounds validation before writing checkpoint forms so undersized allocations fail with a controlled exception instead of risking out-of-bounds writes. Co-authored-by: Cursor --- src/callback.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/callback.h b/src/callback.h index 22e26f8c..003075d9 100644 --- a/src/callback.h +++ b/src/callback.h @@ -107,7 +107,10 @@ class OneWesolowskiCallback: public WesolowskiCallback { return ; if (iteration % kl == 0) { - uint64_t pos = iteration / kl; + const size_t pos = static_cast(iteration / kl); + if (pos >= forms_capacity) { + throw std::runtime_error("OneWesolowskiCallback::OnIteration out of bounds"); + } form* mulf = &forms[pos]; SetForm(type, data, mulf); } From 4ab97b075423ea7c880ea33cb230d64b9dcf844e Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 13 Feb 2026 12:49:10 -0800 Subject: [PATCH 59/78] hw-build: align Windows HW runner with other smoke checks. Build all four HW tool binaries on Windows, run both emu smoke commands, and upload the additional executables so Windows coverage matches Ubuntu and macOS job intent. Co-authored-by: Cursor --- .github/workflows/hw-build.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/hw-build.yml b/.github/workflows/hw-build.yml index 31a95ae2..692e563e 100644 --- a/.github/workflows/hw-build.yml +++ b/.github/workflows/hw-build.yml @@ -226,6 +226,8 @@ jobs: run: | cmake --build build --target emu_hw_test cmake --build build --target hw_test + cmake --build build --target emu_hw_vdf_client + cmake --build build --target hw_vdf_client - name: Smoke test working-directory: "${{ github.workspace }}/build" @@ -237,11 +239,17 @@ jobs: if (Test-Path "$env:GITHUB_WORKSPACE\mpir_gc_x64") { $dllPaths += "$env:GITHUB_WORKSPACE\mpir_gc_x64" } if (Test-Path "$env:GITHUB_WORKSPACE\src\hw\libft4222") { $dllPaths += "$env:GITHUB_WORKSPACE\src\hw\libft4222" } if ($dllPaths.Count -gt 0) { $env:PATH = ($dllPaths -join ';') + ';' + $env:PATH } - if (Test-Path ".\hw_test.exe") { Write-Host "hw_test.exe present" } + if (-not (Test-Path ".\hw_test.exe")) { throw "hw_test.exe is missing" } + if (-not (Test-Path ".\hw_vdf_client.exe")) { throw "hw_vdf_client.exe is missing" } + Write-Host "hw_test.exe and hw_vdf_client.exe present" Write-Host "Running emu_hw_test" .\emu_hw_test.exe 1 2000 if ($LASTEXITCODE -ne 0) { throw "emu_hw_test failed with exit code $LASTEXITCODE" } Write-Host "emu_hw_test completed" + Write-Host "Running emu_hw_vdf_client --list" + .\emu_hw_vdf_client.exe --list + if ($LASTEXITCODE -ne 0) { throw "emu_hw_vdf_client --list failed with exit code $LASTEXITCODE" } + Write-Host "emu_hw_vdf_client --list completed" - name: Upload Artifacts uses: actions/upload-artifact@v5 @@ -250,6 +258,8 @@ jobs: path: | ${{ github.workspace }}/build/emu_hw_test.exe ${{ github.workspace }}/build/hw_test.exe + ${{ github.workspace }}/build/emu_hw_vdf_client.exe + ${{ github.workspace }}/build/hw_vdf_client.exe ${{ github.workspace }}/src/hw/libft4222/libft4222.dll ${{ github.workspace }}/src/hw/libft4222/ftd2xx.dll ${{ github.workspace }}/src/hw/libft4222/libft4222.lib From 61e9df88e99ffc8031422883e2f12e5ffbe687ca Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 13 Feb 2026 12:54:44 -0800 Subject: [PATCH 60/78] hw-client: make hw_vdf_client option parsing Windows-safe. Replace getopt-based parsing with a portable long-option parser in hw_vdf_client so Windows builds can compile emu_hw_vdf_client and hw_vdf_client without missing getopt.h. Co-authored-by: Cursor --- src/hw/hw_vdf_client.cpp | 102 +++++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 41 deletions(-) diff --git a/src/hw/hw_vdf_client.cpp b/src/hw/hw_vdf_client.cpp index e6fc3515..cd18f01f 100644 --- a/src/hw/hw_vdf_client.cpp +++ b/src/hw/hw_vdf_client.cpp @@ -7,7 +7,7 @@ #include "pll_freqs.hpp" #include -#include +#include #include #ifdef _WIN32 @@ -480,20 +480,7 @@ void event_loop(struct vdf_client *client) int parse_opts(int argc, char **argv, struct vdf_client_opts *opts) { - const struct option long_opts[] = { - {"freq", required_argument, NULL, 1}, - {"voltage", required_argument, NULL, 1}, - {"ip", required_argument, NULL, 1}, - {"vdfs-mask", required_argument, NULL, 1}, - {"vdf-threads", required_argument, NULL, 1}, - {"proof-threads", required_argument, NULL, 1}, - {"list", no_argument, NULL, 1}, - {"auto-freq-period", required_argument, NULL, 1}, - {"max-freq", required_argument, NULL, 1}, - {0} - }; - int long_idx = -1; - int ret; + int argi = 1; opts->voltage = HW_VDF_DEF_VOLTAGE; opts->freq = HW_VDF_DEF_FREQ; @@ -507,32 +494,65 @@ int parse_opts(int argc, char **argv, struct vdf_client_opts *opts) opts->vpo.max_proof_threads = 0; opts->vdfs_mask = 0; - while ((ret = getopt_long(argc, argv, "", long_opts, &long_idx)) == 1) { - if (long_idx == 0) { - opts->freq = strtod(optarg, NULL); - } else if (long_idx == 1) { - opts->voltage = strtod(optarg, NULL); - } else if (long_idx == 2) { - opts->ip = ntohl(inet_addr(optarg)); - } else if (long_idx == 3) { - opts->vdfs_mask = strtoul(optarg, NULL, 0); - } else if (long_idx == 4) { - opts->vpo.max_aux_threads = strtoul(optarg, NULL, 0); - } else if (long_idx == 5) { - opts->vpo.max_proof_threads = strtoul(optarg, NULL, 0); - } else if (long_idx == 6) { + while (argi < argc && !strncmp(argv[argi], "--", 2)) { + const char *name = argv[argi] + 2; + const char *value = nullptr; + char name_buf[32] = {0}; + const char *eq = strchr(name, '='); + + if (eq) { + size_t len = static_cast(eq - name); + if (len == 0 || len >= sizeof(name_buf)) { + LOG_SIMPLE("Invalid option"); + return -1; + } + memcpy(name_buf, name, len); + name = name_buf; + value = eq + 1; + } + + if (!strcmp(name, "list")) { + if (value) { + LOG_SIMPLE("Invalid option"); + return -1; + } opts->do_list = true; - } else if (long_idx == 7) { + argi++; + continue; + } + + if (!value) { + if (argi + 1 >= argc) { + LOG_SIMPLE("Invalid option"); + return -1; + } + value = argv[++argi]; + } + + if (!strcmp(name, "freq")) { + opts->freq = strtod(value, NULL); + } else if (!strcmp(name, "voltage")) { + opts->voltage = strtod(value, NULL); + } else if (!strcmp(name, "ip")) { + opts->ip = ntohl(inet_addr(value)); + } else if (!strcmp(name, "vdfs-mask")) { + opts->vdfs_mask = strtoul(value, NULL, 0); + } else if (!strcmp(name, "vdf-threads")) { + opts->vpo.max_aux_threads = strtoul(value, NULL, 0); + } else if (!strcmp(name, "proof-threads")) { + opts->vpo.max_proof_threads = strtoul(value, NULL, 0); + } else if (!strcmp(name, "auto-freq-period")) { opts->auto_freq = true; - opts->auto_freq_period = strtoul(optarg, NULL, 0); - } else if (long_idx == 8) { - opts->max_freq = strtod(optarg, NULL); + opts->auto_freq_period = strtoul(value, NULL, 0); + } else if (!strcmp(name, "max-freq")) { + opts->max_freq = strtod(value, NULL); + } else { + LOG_SIMPLE("Invalid option"); + return -1; } + argi++; } - if (ret != -1) { - LOG_SIMPLE("Invalid option"); - return -1; - } + if (opts->do_list) { return 0; } @@ -570,12 +590,12 @@ int parse_opts(int argc, char **argv, struct vdf_client_opts *opts) return -1; } - if (optind == argc) { + if (argi == argc) { return -1; } - opts->port = atoi(argv[optind]); - if (argc > optind + 1) { - opts->n_vdfs = atoi(argv[optind + 1]); + opts->port = atoi(argv[argi]); + if (argc > argi + 1) { + opts->n_vdfs = atoi(argv[argi + 1]); } if (!opts->port || opts->n_vdfs < 1 || opts->n_vdfs > 3) { LOG_SIMPLE("Invalid port or VDF count"); From 43e7d7d08d65aae6302cd2fc9bee9ded64805326 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 13 Feb 2026 13:06:16 -0800 Subject: [PATCH 61/78] hw-client: use Windows-compatible signal handlers in hw_vdf_client. Guard POSIX sigaction usage behind non-Windows and use signal() on Windows so hw_vdf_client targets compile under clang-cl in the Windows HW CI job. Co-authored-by: Cursor --- src/hw/hw_vdf_client.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/hw/hw_vdf_client.cpp b/src/hw/hw_vdf_client.cpp index cd18f01f..eb93b62c 100644 --- a/src/hw/hw_vdf_client.cpp +++ b/src/hw/hw_vdf_client.cpp @@ -608,7 +608,9 @@ int parse_opts(int argc, char **argv, struct vdf_client_opts *opts) int hw_vdf_client_main(int argc, char **argv) { struct vdf_client client; +#ifndef _WIN32 struct sigaction sa = {0}; +#endif #ifdef _WIN32 WSADATA wsa_data; @@ -645,9 +647,14 @@ int hw_vdf_client_main(int argc, char **argv) init_vdf_client(&client); +#ifdef _WIN32 + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); +#else sa.sa_handler = signal_handler; sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); +#endif event_loop(&client); From e7441dbc13af355ef0df38a2ee03154e99ad13d8 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 13 Feb 2026 13:18:15 -0800 Subject: [PATCH 62/78] callback: harden one-weso capacity calculation. Validate checkpoint stride and forms capacity arithmetic before allocation so malformed parameters fail fast instead of risking undersized storage. Co-authored-by: Cursor --- src/callback.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/callback.h b/src/callback.h index 003075d9..35d48f32 100644 --- a/src/callback.h +++ b/src/callback.h @@ -94,10 +94,21 @@ class OneWesolowskiCallback: public WesolowskiCallback { k = 10; l = 1; } - kl = k * l; - uint64_t space_needed = wanted_iter / (k * l) + 100; + const uint64_t step = static_cast(k) * static_cast(l); + if (step == 0) { + throw std::overflow_error("OneWesolowskiCallback invalid checkpoint stride"); + } + if (step > static_cast(std::numeric_limits::max())) { + throw std::overflow_error("OneWesolowskiCallback checkpoint stride too large"); + } + kl = static_cast(step); + + const uint64_t space_needed = wanted_iter / step + 100; + if (space_needed > static_cast(std::numeric_limits::max())) { + throw std::overflow_error("OneWesolowskiCallback forms capacity overflow"); + } forms_capacity = static_cast(space_needed); - forms.reset(new form[space_needed]); + forms.reset(new form[forms_capacity]); forms[0] = f; } From 173222e150d2a8316c01571a0e3c42ab509a0872 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 13 Feb 2026 13:20:35 -0800 Subject: [PATCH 63/78] callback: publish two-weso switch state with release semantics. Fix a real race where readers could observe a new switch_iters value with a stale switch_index during the 2-wesolowski constant transition, which could compute an incorrect checkpoint slot. Use release store on switch_iters to pair with existing acquire load and preserve correct metadata visibility with negligible performance impact. Co-authored-by: Cursor --- src/callback.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/callback.h b/src/callback.h index 35d48f32..b91c4c57 100644 --- a/src/callback.h +++ b/src/callback.h @@ -154,7 +154,9 @@ class TwoWesolowskiCallback: public WesolowskiCallback { // Publish transition metadata first, then publish kl=100. // OnIteration acquires kl before consuming switch state. switch_index.store(num_iters / 10, std::memory_order_relaxed); - switch_iters.store(static_cast(num_iters), std::memory_order_relaxed); + // Readers branch on switch_iters and then consume switch_index. + // Release here pairs with acquire load in GetPositionUnlocked(). + switch_iters.store(static_cast(num_iters), std::memory_order_release); kl.store(100, std::memory_order_release); } From 54e60ef0f080ccac8bbce7b2236a8b1facfeab9e Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 13 Feb 2026 13:25:32 -0800 Subject: [PATCH 64/78] parameters: gate AVX runtime flags on OS state. Prevent AVX2/AVX512 IFMA enablement unless OSXSAVE is present and XCR0 has required AVX/AVX-512 state bits, avoiding illegal-instruction crashes when OS context management is unavailable. Co-authored-by: Cursor --- src/parameters.h | 65 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/src/parameters.h b/src/parameters.h index 07a49de7..53a19341 100644 --- a/src/parameters.h +++ b/src/parameters.h @@ -33,6 +33,10 @@ extern bool enable_all_instructions; #include #include #include +#include +#if defined(_MSC_VER) +#include +#endif inline std::atomic bAVX2{false}; inline std::atomic enable_avx512_ifma{false}; @@ -82,10 +86,18 @@ inline void init_avx_flags() const bool enable_avx512 = env_flag("CHIA_ENABLE_AVX512_IFMA"); const bool force_avx512 = env_flag("CHIA_FORCE_AVX512_IFMA"); int info[4] = {0}; + int info1[4] = {0}; #if defined(_MSC_VER) + __cpuid(info1, 0x1); __cpuid(info, 0x7); #elif defined(__GNUC__) || defined(__clang__) #if defined(ARCH_X86) && defined(__PIC__) + __asm__ __volatile__ ( + "xchg{l} {%%}ebx, %k1;" + "cpuid;" + "xchg{l} {%%}ebx, %k1;" + : "=a"(info1[0]), "=&r"(info1[1]), "=c"(info1[2]), "=d"(info1[3]) : "a"(0x1), "c"(0) + ); __asm__ __volatile__ ( "xchg{l} {%%}ebx, %k1;" "cpuid;" @@ -93,30 +105,70 @@ inline void init_avx_flags() : "=a"(info[0]), "=&r"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(0x7), "c"(0) ); #else + __asm__ __volatile__ ( + "cpuid" : "=a"(info1[0]), "=b"(info1[1]), "=c"(info1[2]), "=d"(info1[3]) : "a"(0x1), "c"(0) + ); __asm__ __volatile__ ( "cpuid" : "=a"(info[0]), "=b"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(0x7), "c"(0) ); #endif #endif + uint64_t xcr0 = 0; + bool osxsave_enabled = false; +#if defined(_MSC_VER) + const int OSXSAVE = 1 << 27; + osxsave_enabled = ((info1[2] & OSXSAVE) == OSXSAVE); + if (osxsave_enabled) { + xcr0 = static_cast(_xgetbv(0)); + } +#elif defined(__GNUC__) || defined(__clang__) + const int OSXSAVE = 1 << 27; + osxsave_enabled = ((info1[2] & OSXSAVE) == OSXSAVE); + if (osxsave_enabled) { + uint32_t eax = 0; + uint32_t edx = 0; + __asm__ __volatile__ ( + ".byte 0x0f, 0x01, 0xd0" + : "=a"(eax), "=d"(edx) + : "c"(0) + ); + xcr0 = (static_cast(edx) << 32) | eax; + } +#endif + + constexpr uint64_t XCR0_XMM_MASK = (1ULL << 1); + constexpr uint64_t XCR0_YMM_MASK = (1ULL << 2); + constexpr uint64_t XCR0_AVX_MASK = XCR0_XMM_MASK | XCR0_YMM_MASK; + constexpr uint64_t XCR0_AVX512_MASK = XCR0_AVX_MASK | (1ULL << 5) | (1ULL << 6) | (1ULL << 7); + + const int AVX = 1 << 28; const int AVX2 = 1<<5; const int ADX = 1<<19; const int AVX512F = 1<<16; const int AVX512IFMA = 1<<21; + bool avxbit = ((info1[2] & AVX) == AVX); bool avx2bit = ((info[1] & AVX2) == AVX2); bool adxbit = ((info[1] & ADX) == ADX); bool avx512fbit = ((info[1] & AVX512F) == AVX512F); bool avx512ifmabit = ((info[1] & AVX512IFMA) == AVX512IFMA); + bool avx_os_state = osxsave_enabled && ((xcr0 & XCR0_AVX_MASK) == XCR0_AVX_MASK); + bool avx512_os_state = osxsave_enabled && ((xcr0 & XCR0_AVX512_MASK) == XCR0_AVX512_MASK); if (disable_avx2) { bAVX2.store(false, std::memory_order_relaxed); } else if (force_avx2) { bAVX2.store(true, std::memory_order_relaxed); } else { - bAVX2.store(avx2bit && adxbit, std::memory_order_relaxed); + bAVX2.store(avxbit && avx2bit && adxbit && avx_os_state, std::memory_order_relaxed); } if (bAVX2.load(std::memory_order_relaxed) && should_log_avx()) { - std::fprintf(stderr, "AVX2 enabled (avx2=%d adx=%d)\n", avx2bit ? 1 : 0, adxbit ? 1 : 0); + std::fprintf(stderr, "AVX2 enabled (avx=%d avx2=%d adx=%d osxsave=%d xcr0=0x%llx)\n", + avxbit ? 1 : 0, + avx2bit ? 1 : 0, + adxbit ? 1 : 0, + osxsave_enabled ? 1 : 0, + static_cast(xcr0)); } if (disable_avx512) { @@ -124,12 +176,17 @@ inline void init_avx_flags() } else if (force_avx512) { enable_avx512_ifma.store(true, std::memory_order_relaxed); } else if (enable_avx512) { - enable_avx512_ifma.store(avx512fbit && avx512ifmabit, std::memory_order_relaxed); + enable_avx512_ifma.store(avxbit && avx512fbit && avx512ifmabit && avx512_os_state, std::memory_order_relaxed); } else { enable_avx512_ifma.store(false, std::memory_order_relaxed); } if (enable_avx512_ifma.load(std::memory_order_relaxed) && should_log_avx()) { - std::fprintf(stderr, "AVX512 IFMA enabled (f=%d ifma=%d)\n", avx512fbit ? 1 : 0, avx512ifmabit ? 1 : 0); + std::fprintf(stderr, "AVX512 IFMA enabled (avx=%d f=%d ifma=%d osxsave=%d xcr0=0x%llx)\n", + avxbit ? 1 : 0, + avx512fbit ? 1 : 0, + avx512ifmabit ? 1 : 0, + osxsave_enabled ? 1 : 0, + static_cast(xcr0)); } #elif defined(ARCH_ARM) bAVX2.store(false, std::memory_order_relaxed); From c5414c4ab8fb745c24a2307f3390081bc39acfbc Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 13 Feb 2026 13:27:01 -0800 Subject: [PATCH 65/78] parameters: keep AVX force flags OS-state safe. Avoid enabling AVX2/AVX512 execution paths when the OS hasn't enabled xstate, even when force env toggles are set, preventing illegal-instruction crashes. Co-authored-by: Cursor --- src/parameters.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/parameters.h b/src/parameters.h index 53a19341..bf700350 100644 --- a/src/parameters.h +++ b/src/parameters.h @@ -158,7 +158,8 @@ inline void init_avx_flags() if (disable_avx2) { bAVX2.store(false, std::memory_order_relaxed); } else if (force_avx2) { - bAVX2.store(true, std::memory_order_relaxed); + // Force mode bypasses CPUID feature gating but still must respect OS xstate. + bAVX2.store(avx_os_state, std::memory_order_relaxed); } else { bAVX2.store(avxbit && avx2bit && adxbit && avx_os_state, std::memory_order_relaxed); } @@ -174,7 +175,8 @@ inline void init_avx_flags() if (disable_avx512) { enable_avx512_ifma.store(false, std::memory_order_relaxed); } else if (force_avx512) { - enable_avx512_ifma.store(true, std::memory_order_relaxed); + // Force mode bypasses CPUID feature gating but still must respect OS xstate. + enable_avx512_ifma.store(avx512_os_state, std::memory_order_relaxed); } else if (enable_avx512) { enable_avx512_ifma.store(avxbit && avx512fbit && avx512ifmabit && avx512_os_state, std::memory_order_relaxed); } else { From c0e4db724ba0bad1c8f975d2481c26fc16aeacb1 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 13 Feb 2026 13:29:43 -0800 Subject: [PATCH 66/78] callback: atomically snapshot two-weso switch metadata Store switch index and switch iteration in one atomic state so readers cannot observe mixed transition values during the 10-to-100 checkpoint switch. Co-authored-by: Cursor --- src/callback.h | 45 +++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/src/callback.h b/src/callback.h index b91c4c57..a1a39a16 100644 --- a/src/callback.h +++ b/src/callback.h @@ -146,17 +146,15 @@ class TwoWesolowskiCallback: public WesolowskiCallback { forms.reset(new form[space_needed]); forms[0] = f; kl.store(10, std::memory_order_relaxed); - switch_iters.store(-1, std::memory_order_relaxed); - switch_index.store(0, std::memory_order_relaxed); + transition_state.store(EncodeTransitionState(/*switch_index=*/0, /*switch_iters=*/-1), std::memory_order_relaxed); } void IncreaseConstants(uint64_t num_iters) { - // Publish transition metadata first, then publish kl=100. - // OnIteration acquires kl before consuming switch state. - switch_index.store(num_iters / 10, std::memory_order_relaxed); - // Readers branch on switch_iters and then consume switch_index. - // Release here pairs with acquire load in GetPositionUnlocked(). - switch_iters.store(static_cast(num_iters), std::memory_order_release); + // Publish transition metadata as one atomic snapshot, then publish kl=100. + transition_state.store( + EncodeTransitionState(num_iters / 10, static_cast(num_iters)), + std::memory_order_release + ); kl.store(100, std::memory_order_release); } @@ -165,11 +163,12 @@ class TwoWesolowskiCallback: public WesolowskiCallback { } int GetPositionUnlocked(uint64_t power) const { - const int64_t current_switch_iters = switch_iters.load(std::memory_order_acquire); + const uint64_t snapshot = transition_state.load(std::memory_order_acquire); + const int64_t current_switch_iters = DecodeSwitchIters(snapshot); if (current_switch_iters == -1 || power < static_cast(current_switch_iters)) { return power / 10; } else { - const uint64_t current_switch_index = switch_index.load(std::memory_order_relaxed); + const uint64_t current_switch_index = DecodeSwitchIndex(snapshot); return static_cast(current_switch_index + (power - static_cast(current_switch_iters)) / 100); } } @@ -209,8 +208,30 @@ class TwoWesolowskiCallback: public WesolowskiCallback { } private: - std::atomic switch_index{0}; - std::atomic switch_iters{-1}; + static uint64_t EncodeTransitionState(uint64_t switch_index_value, int64_t switch_iters_value) { + if (switch_index_value > static_cast(std::numeric_limits::max())) { + throw std::overflow_error("TwoWesolowskiCallback switch_index overflow"); + } + // Persist switch_iters in 32 bits with +1 encoding to represent -1 (unset) as 0. + if (switch_iters_value < -1 || + switch_iters_value > static_cast(std::numeric_limits::max() - 1)) { + throw std::overflow_error("TwoWesolowskiCallback switch_iters overflow"); + } + const uint32_t encoded_iters = static_cast(switch_iters_value + 1); + return (static_cast(encoded_iters) << 32) | + static_cast(static_cast(switch_index_value)); + } + + static uint64_t DecodeSwitchIndex(uint64_t state) { + return static_cast(state & 0xffffffffULL); + } + + static int64_t DecodeSwitchIters(uint64_t state) { + const uint32_t encoded_iters = static_cast(state >> 32); + return static_cast(encoded_iters) - 1; + } + + std::atomic transition_state{0}; std::atomic kl{10}; std::mutex forms_mutex; }; From a3abd4efebee541f58a7cc20789832366e12e909 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 13 Feb 2026 13:36:27 -0800 Subject: [PATCH 67/78] hw-client: balance Winsock startup/cleanup on early exits Ensure hw_vdf_client_main calls WSACleanup on parse, list, and init_hw failure paths after successful WSAStartup so repeated in-process invocations do not leak Winsock references. Co-authored-by: Cursor --- src/hw/hw_vdf_client.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/hw/hw_vdf_client.cpp b/src/hw/hw_vdf_client.cpp index eb93b62c..97fe95ad 100644 --- a/src/hw/hw_vdf_client.cpp +++ b/src/hw/hw_vdf_client.cpp @@ -632,16 +632,26 @@ int hw_vdf_client_main(int argc, char **argv) " --auto-freq-period N - auto-adjust frequency every N seconds [0, 10 - inf]\n" " --list - list available devices and exit", argv[0], (int)HW_VDF_DEF_FREQ, HW_VDF_DEF_VOLTAGE); +#ifdef _WIN32 + WSACleanup(); +#endif return 1; } if (client.opts.do_list) { LOG_SIMPLE("List of available devices:"); - return list_hw() ? 1 : 0; + const int ret = list_hw() ? 1 : 0; +#ifdef _WIN32 + WSACleanup(); +#endif + return ret; } client.drv = init_hw(client.opts.freq, client.opts.voltage); if (!client.drv) { +#ifdef _WIN32 + WSACleanup(); +#endif return 1; } From 443ff5e53a75c2604f788d263bf7d3e2fb22158d Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 13 Feb 2026 13:43:00 -0800 Subject: [PATCH 68/78] callback: lock two-weso transition publication Guard IncreaseConstants and GetPosition with forms_mutex so transition state publication and form index reads share one synchronization domain at the 10->100 switch. Co-authored-by: Cursor --- src/callback.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/callback.h b/src/callback.h index a1a39a16..1098686d 100644 --- a/src/callback.h +++ b/src/callback.h @@ -150,6 +150,7 @@ class TwoWesolowskiCallback: public WesolowskiCallback { } void IncreaseConstants(uint64_t num_iters) { + std::lock_guard lk(forms_mutex); // Publish transition metadata as one atomic snapshot, then publish kl=100. transition_state.store( EncodeTransitionState(num_iters / 10, static_cast(num_iters)), @@ -159,6 +160,7 @@ class TwoWesolowskiCallback: public WesolowskiCallback { } int GetPosition(uint64_t power) { + std::lock_guard lk(forms_mutex); return GetPositionUnlocked(power); } From 8638d3acb0caa16981e83148d8f06a29e863b164 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 13 Feb 2026 13:44:01 -0800 Subject: [PATCH 69/78] hw-client: parse positional args independently from flags Collect positional port/VDF arguments while scanning all options so CLI parsing remains valid regardless of argument ordering. Co-authored-by: Cursor --- src/hw/hw_vdf_client.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/hw/hw_vdf_client.cpp b/src/hw/hw_vdf_client.cpp index 97fe95ad..90ed06f7 100644 --- a/src/hw/hw_vdf_client.cpp +++ b/src/hw/hw_vdf_client.cpp @@ -481,6 +481,8 @@ void event_loop(struct vdf_client *client) int parse_opts(int argc, char **argv, struct vdf_client_opts *opts) { int argi = 1; + int positional_count = 0; + const char *positionals[2] = {nullptr, nullptr}; opts->voltage = HW_VDF_DEF_VOLTAGE; opts->freq = HW_VDF_DEF_FREQ; @@ -494,7 +496,16 @@ int parse_opts(int argc, char **argv, struct vdf_client_opts *opts) opts->vpo.max_proof_threads = 0; opts->vdfs_mask = 0; - while (argi < argc && !strncmp(argv[argi], "--", 2)) { + while (argi < argc) { + if (strncmp(argv[argi], "--", 2) != 0) { + if (positional_count < 2) { + positionals[positional_count] = argv[argi]; + } + positional_count++; + argi++; + continue; + } + const char *name = argv[argi] + 2; const char *value = nullptr; char name_buf[32] = {0}; @@ -590,12 +601,12 @@ int parse_opts(int argc, char **argv, struct vdf_client_opts *opts) return -1; } - if (argi == argc) { + if (positional_count == 0) { return -1; } - opts->port = atoi(argv[argi]); - if (argc > argi + 1) { - opts->n_vdfs = atoi(argv[argi + 1]); + opts->port = atoi(positionals[0]); + if (positional_count > 1) { + opts->n_vdfs = atoi(positionals[1]); } if (!opts->port || opts->n_vdfs < 1 || opts->n_vdfs > 3) { LOG_SIMPLE("Invalid port or VDF count"); From dbe773cfa860b06035e65a0d6038f7a944b69fa1 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 13 Feb 2026 13:50:35 -0800 Subject: [PATCH 70/78] hw-client: reject invalid positional ports Disallow single-dash tokens from being treated as positional arguments and parse PORT/N_VDFS with strict numeric bounds so negative values cannot wrap through htons to unintended endpoints. Co-authored-by: Cursor --- src/hw/hw_vdf_client.cpp | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/hw/hw_vdf_client.cpp b/src/hw/hw_vdf_client.cpp index 90ed06f7..5cc111d8 100644 --- a/src/hw/hw_vdf_client.cpp +++ b/src/hw/hw_vdf_client.cpp @@ -7,6 +7,7 @@ #include "pll_freqs.hpp" #include +#include #include #include @@ -498,6 +499,10 @@ int parse_opts(int argc, char **argv, struct vdf_client_opts *opts) while (argi < argc) { if (strncmp(argv[argi], "--", 2) != 0) { + if (argv[argi][0] == '-') { + LOG_SIMPLE("Invalid option"); + return -1; + } if (positional_count < 2) { positionals[positional_count] = argv[argi]; } @@ -604,11 +609,25 @@ int parse_opts(int argc, char **argv, struct vdf_client_opts *opts) if (positional_count == 0) { return -1; } - opts->port = atoi(positionals[0]); + { + char *end = nullptr; + long parsed_port = strtol(positionals[0], &end, 10); + if (!positionals[0][0] || (end && *end) || parsed_port < 1 || parsed_port > 65535) { + LOG_SIMPLE("Invalid port or VDF count"); + return -1; + } + opts->port = static_cast(parsed_port); + } if (positional_count > 1) { - opts->n_vdfs = atoi(positionals[1]); + char *end = nullptr; + long parsed_n_vdfs = strtol(positionals[1], &end, 10); + if (!positionals[1][0] || (end && *end) || parsed_n_vdfs < 1 || parsed_n_vdfs > 3) { + LOG_SIMPLE("Invalid port or VDF count"); + return -1; + } + opts->n_vdfs = static_cast(parsed_n_vdfs); } - if (!opts->port || opts->n_vdfs < 1 || opts->n_vdfs > 3) { + if (opts->n_vdfs < 1 || opts->n_vdfs > 3) { LOG_SIMPLE("Invalid port or VDF count"); return -1; } From 6fc45283f60a24bc6dae2673f8402896115d8ee8 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 13 Feb 2026 13:54:28 -0800 Subject: [PATCH 71/78] hw-client: harden Winsock cleanup with RAII Use a local guard in hw_vdf_client_main() so any successful WSAStartup() is always paired with WSACleanup(), including all early-return paths. Co-authored-by: Cursor --- src/hw/hw_vdf_client.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/hw/hw_vdf_client.cpp b/src/hw/hw_vdf_client.cpp index 5cc111d8..b71f01c4 100644 --- a/src/hw/hw_vdf_client.cpp +++ b/src/hw/hw_vdf_client.cpp @@ -643,11 +643,22 @@ int hw_vdf_client_main(int argc, char **argv) #endif #ifdef _WIN32 + struct WinsockGuard { + bool started = false; + + ~WinsockGuard() { + if (started) { + WSACleanup(); + } + } + } winsock_guard; + WSADATA wsa_data; if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) { LOG_SIMPLE("Failed to initialize Winsock"); return 1; } + winsock_guard.started = true; #endif if (parse_opts(argc, argv, &client.opts) < 0) { @@ -662,26 +673,17 @@ int hw_vdf_client_main(int argc, char **argv) " --auto-freq-period N - auto-adjust frequency every N seconds [0, 10 - inf]\n" " --list - list available devices and exit", argv[0], (int)HW_VDF_DEF_FREQ, HW_VDF_DEF_VOLTAGE); -#ifdef _WIN32 - WSACleanup(); -#endif return 1; } if (client.opts.do_list) { LOG_SIMPLE("List of available devices:"); const int ret = list_hw() ? 1 : 0; -#ifdef _WIN32 - WSACleanup(); -#endif return ret; } client.drv = init_hw(client.opts.freq, client.opts.voltage); if (!client.drv) { -#ifdef _WIN32 - WSACleanup(); -#endif return 1; } @@ -700,9 +702,6 @@ int hw_vdf_client_main(int argc, char **argv) stop_hw(client.drv); clear_vdf_client(&client); -#ifdef _WIN32 - WSACleanup(); -#endif return 0; } From 54f7b8b34d0fdf7f7fbab7a74a3020484c0d1da1 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Fri, 13 Feb 2026 15:01:45 -0800 Subject: [PATCH 72/78] callback: harden two-weso transition snapshot semantics Address Opus review follow-ups by making checkpoint position/stride decisions derive from a single transition_state snapshot and widening two-weso position indices to size_t to avoid narrowing risk. Also document the single-thread invariant for cached_form in TwoWesolowskiProver::GetForm. Co-authored-by: Cursor --- src/callback.h | 50 +++++++++++++++++++++++++++++++------------------- src/provers.h | 2 ++ 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/callback.h b/src/callback.h index 1098686d..ecf7fff8 100644 --- a/src/callback.h +++ b/src/callback.h @@ -151,7 +151,7 @@ class TwoWesolowskiCallback: public WesolowskiCallback { void IncreaseConstants(uint64_t num_iters) { std::lock_guard lk(forms_mutex); - // Publish transition metadata as one atomic snapshot, then publish kl=100. + // Publish transition metadata first. `kl` is only a fast-path hint. transition_state.store( EncodeTransitionState(num_iters / 10, static_cast(num_iters)), std::memory_order_release @@ -159,33 +159,28 @@ class TwoWesolowskiCallback: public WesolowskiCallback { kl.store(100, std::memory_order_release); } - int GetPosition(uint64_t power) { + size_t GetPosition(uint64_t power) { std::lock_guard lk(forms_mutex); return GetPositionUnlocked(power); } - int GetPositionUnlocked(uint64_t power) const { + size_t GetPositionUnlocked(uint64_t power) const { const uint64_t snapshot = transition_state.load(std::memory_order_acquire); - const int64_t current_switch_iters = DecodeSwitchIters(snapshot); - if (current_switch_iters == -1 || power < static_cast(current_switch_iters)) { - return power / 10; - } else { - const uint64_t current_switch_index = DecodeSwitchIndex(snapshot); - return static_cast(current_switch_index + (power - static_cast(current_switch_iters)) / 100); - } + return GetPositionFromSnapshot(power, snapshot); } form GetFormCopy(uint64_t power) { std::lock_guard lk(forms_mutex); - const int pos = GetPositionUnlocked(power); - if (pos < 0 || static_cast(pos) >= forms_capacity) { + const size_t pos = GetPositionUnlocked(power); + if (pos >= forms_capacity) { throw std::runtime_error("TwoWesolowskiCallback::GetFormCopy out of bounds"); } - return forms[static_cast(pos)]; + return forms[pos]; } bool LargeConstants() { - return kl.load(std::memory_order_relaxed) == 100; + const uint64_t snapshot = transition_state.load(std::memory_order_acquire); + return DecodeSwitchIters(snapshot) != -1; } void OnIteration(int type, void *data, uint64_t iteration) { @@ -197,15 +192,16 @@ class TwoWesolowskiCallback: public WesolowskiCallback { } std::lock_guard lk(forms_mutex); - const uint32_t locked_kl = kl.load(std::memory_order_acquire); - if (iteration % locked_kl != 0) { + const uint64_t snapshot = transition_state.load(std::memory_order_acquire); + const uint32_t effective_kl = GetEffectiveKl(iteration, snapshot); + if (iteration % effective_kl != 0) { return; } - const int pos = GetPositionUnlocked(iteration); - if (pos < 0 || static_cast(pos) >= forms_capacity) { + const size_t pos = GetPositionFromSnapshot(iteration, snapshot); + if (pos >= forms_capacity) { throw std::runtime_error("TwoWesolowskiCallback::OnIteration out of bounds"); } - form* mulf = &forms[static_cast(pos)]; + form* mulf = &forms[pos]; SetForm(type, data, mulf); } @@ -233,6 +229,22 @@ class TwoWesolowskiCallback: public WesolowskiCallback { return static_cast(encoded_iters) - 1; } + static uint32_t GetEffectiveKl(uint64_t power, uint64_t state) { + const int64_t current_switch_iters = DecodeSwitchIters(state); + return (current_switch_iters == -1 || power < static_cast(current_switch_iters)) ? 10U : 100U; + } + + static size_t GetPositionFromSnapshot(uint64_t power, uint64_t state) { + const int64_t current_switch_iters = DecodeSwitchIters(state); + if (current_switch_iters == -1 || power < static_cast(current_switch_iters)) { + return static_cast(power / 10); + } + const uint64_t current_switch_index = DecodeSwitchIndex(state); + return static_cast( + current_switch_index + (power - static_cast(current_switch_iters)) / 100 + ); + } + std::atomic transition_state{0}; std::atomic kl{10}; std::mutex forms_mutex; diff --git a/src/provers.h b/src/provers.h index 8d8437bb..22165d40 100644 --- a/src/provers.h +++ b/src/provers.h @@ -74,6 +74,8 @@ class TwoWesolowskiProver : public Prover{ virtual form* GetForm(uint64_t i) { const uint64_t power = done_iterations + i * k * l; + // `GenerateProof()` calls this on a single worker thread per prover instance. + // Returning `&cached_form` is safe under that invariant. cached_form = weso->GetFormCopy(power); return &cached_form; } From 06db65d44d4b338b859242d9c719fb6d87a55b99 Mon Sep 17 00:00:00 2001 From: earl Date: Mon, 16 Feb 2026 22:04:15 +0100 Subject: [PATCH 73/78] Fix "One Definition Rule" Violation for Prover::GetForm --- src/hw/hw_proof.cpp | 6 +++--- src/vdf_base.hpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hw/hw_proof.cpp b/src/hw/hw_proof.cpp index 593f6042..4b510f49 100644 --- a/src/hw/hw_proof.cpp +++ b/src/hw/hw_proof.cpp @@ -576,13 +576,13 @@ class HwProver : public ParallelProver { pos_offset = segm.start / vdf->interval; } - form* GetForm(uint64_t pos) { + form GetForm(uint64_t pos) { pos += pos_offset; if (hw_proof_wait_value(vdf, pos)) { // Provide arbitrary value when stopping - proof won't be computed - return &vdf->values[0][0]; + return vdf->values[0][0]; } - return hw_proof_value_at(vdf, pos); + return *hw_proof_value_at(vdf, pos); } void start() { diff --git a/src/vdf_base.hpp b/src/vdf_base.hpp index 71ef0bb0..8b5463dd 100644 --- a/src/vdf_base.hpp +++ b/src/vdf_base.hpp @@ -267,7 +267,7 @@ class Prover { is_finished = false; } - virtual form* GetForm(uint64_t iteration) = 0; + virtual form GetForm(uint64_t iteration) = 0; virtual void start() = 0; virtual void stop() = 0; virtual bool PerformExtraStep() = 0; From 3fc72ee136184a1b86f2af323eb6a51037c9c125 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Mon, 16 Feb 2026 14:42:28 -0800 Subject: [PATCH 74/78] prover: align GetForm return semantics across stacks Match the non-HW prover interfaces with main by returning forms by value, eliminating mixed pointer/value virtual signatures that surfaced after the ODR cherry-pick and destabilized cross-platform builds. Co-authored-by: Cursor --- src/prover_base.hpp | 6 +++--- src/prover_parallel.hpp | 4 ++-- src/provers.h | 16 ++++++---------- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/prover_base.hpp b/src/prover_base.hpp index fb2678da..659718d9 100644 --- a/src/prover_base.hpp +++ b/src/prover_base.hpp @@ -16,7 +16,7 @@ class Prover { is_finished = false; } - virtual form* GetForm(uint64_t iteration) = 0; + virtual form GetForm(uint64_t iteration) = 0; virtual void start() = 0; virtual void stop() = 0; virtual bool PerformExtraStep() = 0; @@ -76,8 +76,8 @@ class Prover { throw std::runtime_error("GenerateProof block index out of bounds"); } if (!PerformExtraStep()) return; - form* tmp = GetForm(i); - nucomp_form(ys[b], ys[b], *tmp, D, L); + form tmp = GetForm(i); + nucomp_form(ys[b], ys[b], tmp, D, L); } } diff --git a/src/prover_parallel.hpp b/src/prover_parallel.hpp index 2f0fde7d..a14120bf 100644 --- a/src/prover_parallel.hpp +++ b/src/prover_parallel.hpp @@ -45,8 +45,8 @@ class ParallelProver : public Prover { if (num_iterations >= k * (i * l + j + 1)) { uint64_t b = GetBlock(i*l + j, k, num_iterations, B); if (!PerformExtraStep()) return; - form* tmp = GetForm(i); - nucomp_form(ys[b], ys[b], *tmp, D, L); + form tmp = GetForm(i); + nucomp_form(ys[b], ys[b], tmp, D, L); } } diff --git a/src/provers.h b/src/provers.h index 22165d40..ffb12450 100644 --- a/src/provers.h +++ b/src/provers.h @@ -18,8 +18,8 @@ class OneWesolowskiProver : public Prover { } } - form* GetForm(uint64_t iteration) { - return &intermediates[iteration]; + form GetForm(uint64_t iteration) { + return intermediates[iteration]; } void start() { @@ -72,12 +72,9 @@ class TwoWesolowskiProver : public Prover{ } } - virtual form* GetForm(uint64_t i) { + virtual form GetForm(uint64_t i) { const uint64_t power = done_iterations + i * k * l; - // `GenerateProof()` calls this on a single worker thread per prover instance. - // Returning `&cached_form` is safe under that invariant. - cached_form = weso->GetFormCopy(power); - return &cached_form; + return weso->GetFormCopy(power); } void stop() { @@ -98,7 +95,6 @@ class TwoWesolowskiProver : public Prover{ TwoWesolowskiCallback* weso; std::atomic& stop_signal; uint64_t done_iterations; - form cached_form; std::thread worker; }; @@ -132,8 +128,8 @@ class InterruptableProver: public Prover { delete(th); } - form* GetForm(uint64_t i) { - return weso->GetForm(done_iterations + i * k * l, bucket); + form GetForm(uint64_t i) { + return *weso->GetForm(done_iterations + i * k * l, bucket); } void start() { From ab7b7c7e0072f7c5b70cd28c7e72dfbbc847529f Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Mon, 16 Feb 2026 18:46:42 -0800 Subject: [PATCH 75/78] asm: add Linux track_asm addressing A/B benchmark path Add a Linux-only switch to compare RIP-relative and absolute track_asm addressing from the same code path, and extend Ubuntu CI to build both variants, emit benchmark deltas, and upload asm/benchmark artifacts for reviewer verification. Co-authored-by: Cursor --- .github/workflows/test.yaml | 75 +++++++++++++++++++++++++++++++++++++ src/asm_base.h | 16 ++++++++ 2 files changed, 91 insertions(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index fc3bcd37..551be645 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -259,6 +259,81 @@ jobs: echo "Benchmarking vdf_bench with 2,000,000 iterations of square_asm" ./vdf_bench square_asm 2000000 + - name: Benchmark track_asm addressing modes (Ubuntu) + if: matrix.config == 'optimized=1' && matrix.os == 'ubuntu-latest' + run: | + set -euo pipefail + cd src + + run_variant() { + local variant="$1" + local variant_cppflags="$2" + echo "Building variant: ${variant}" + make clean + make optimized=1 -f Makefile.vdf-client CPPFLAGS="${variant_cppflags} ${CPPFLAGS:-}" + echo "Benchmarking variant: ${variant}" + ./vdf_bench square_asm 2000000 | tee "../bench_${variant}.txt" + cp asm_compiled.s "../asm_compiled_${variant}.s" + cp avx2_asm_compiled.s "../avx2_asm_compiled_${variant}.s" + cp avx512_asm_compiled.s "../avx512_asm_compiled_${variant}.s" + } + + run_variant "rip_relative" "-DGENERATE_ASM_TRACKING_DATA=1 -DCHIA_LINUX_USE_ABSOLUTE_TRACK_ASM=0" + run_variant "absolute" "-DGENERATE_ASM_TRACKING_DATA=1 -DCHIA_LINUX_USE_ABSOLUTE_TRACK_ASM=1" + + - name: Summarize track_asm addressing benchmark delta (Ubuntu) + if: matrix.config == 'optimized=1' && matrix.os == 'ubuntu-latest' + run: | + python3 - <<'PY' + import pathlib + import re + import sys + + def parse(path): + text = pathlib.Path(path).read_text(encoding="utf-8", errors="replace") + t = re.search(r"Time:\s*(\d+)\s*ms;", text) + s = re.search(r"speed:\s*([0-9]+(?:\.[0-9]+)?)K\s+ips", text) + if not t or not s: + print(f"Could not parse benchmark output in {path}", file=sys.stderr) + sys.exit(1) + return int(t.group(1)), float(s.group(1)) + + rip_ms, rip_kips = parse("bench_rip_relative.txt") + abs_ms, abs_kips = parse("bench_absolute.txt") + + speed_delta_pct = ((abs_kips - rip_kips) / rip_kips) * 100.0 + time_delta_pct = ((abs_ms - rip_ms) / rip_ms) * 100.0 + + print("track_asm addressing benchmark summary") + print(f" rip_relative: time={rip_ms} ms, speed={rip_kips:.1f}K ips") + print(f" absolute: time={abs_ms} ms, speed={abs_kips:.1f}K ips") + print(f" delta: speed={speed_delta_pct:+.2f}% (absolute vs rip_relative), time={time_delta_pct:+.2f}%") + + summary_path = pathlib.Path(pathlib.os.environ["GITHUB_STEP_SUMMARY"]) + with summary_path.open("a", encoding="utf-8") as f: + f.write("## track_asm addressing benchmark (Ubuntu)\n") + f.write("| variant | time (ms) | speed (K ips) |\n") + f.write("|---|---:|---:|\n") + f.write(f"| rip_relative | {rip_ms} | {rip_kips:.1f} |\n") + f.write(f"| absolute | {abs_ms} | {abs_kips:.1f} |\n") + f.write(f"| delta (absolute vs rip_relative) | {time_delta_pct:+.2f}% time | {speed_delta_pct:+.2f}% speed |\n") + PY + + - name: Upload track_asm addressing benchmark artifacts (Ubuntu) + if: matrix.config == 'optimized=1' && matrix.os == 'ubuntu-latest' + uses: actions/upload-artifact@v4 + with: + name: track-asm-addressing-${{ github.run_id }}-${{ github.run_attempt }} + path: | + bench_rip_relative.txt + bench_absolute.txt + asm_compiled_rip_relative.s + asm_compiled_absolute.s + avx2_asm_compiled_rip_relative.s + avx2_asm_compiled_absolute.s + avx512_asm_compiled_rip_relative.s + avx512_asm_compiled_absolute.s + - name: Benchmark vdf_bench square (Windows) if: matrix.config == 'optimized=1' && startsWith(matrix.os, 'windows') shell: pwsh diff --git a/src/asm_base.h b/src/asm_base.h index a1257925..7378c972 100644 --- a/src/asm_base.h +++ b/src/asm_base.h @@ -79,17 +79,33 @@ string track_asm(string comment, string jump_to = "") { assert(!enable_threads); //this code isn't atomic +#ifndef CHIA_LINUX_USE_ABSOLUTE_TRACK_ASM +#define CHIA_LINUX_USE_ABSOLUTE_TRACK_ASM 0 +#endif + +#if defined(CHIAOSX) || defined(CHIA_WINDOWS) || !CHIA_LINUX_USE_ABSOLUTE_TRACK_ASM APPEND_M(str( "MOV [RIP+track_asm_rax], RAX" )); APPEND_M(str( "MOV RAX, [RIP+asm_tracking_data+#]", to_hex(8*(id-1)) )); APPEND_M(str( "LEA RAX, [RAX+1]" )); APPEND_M(str( "MOV [RIP+asm_tracking_data+#], RAX", to_hex(8*(id-1)) )); +#else + APPEND_M(str( "MOV [track_asm_rax], RAX" )); + APPEND_M(str( "MOV RAX, [asm_tracking_data+#]", to_hex(8*(id-1)) )); + APPEND_M(str( "LEA RAX, [RAX+1]" )); + APPEND_M(str( "MOV [asm_tracking_data+#], RAX", to_hex(8*(id-1)) )); +#endif #if defined(CHIAOSX) || defined(CHIA_WINDOWS) APPEND_M(str( "LEA RAX, [RIP+#] ", comment_label )); #else APPEND_M(str( "MOV RAX, OFFSET FLAT:#", comment_label )); #endif +#if defined(CHIAOSX) || defined(CHIA_WINDOWS) || !CHIA_LINUX_USE_ABSOLUTE_TRACK_ASM APPEND_M(str( "MOV [RIP+asm_tracking_data_comments+#], RAX", to_hex(8*(id-1)) )); APPEND_M(str( "MOV RAX, [RIP+track_asm_rax]" )); +#else + APPEND_M(str( "MOV [asm_tracking_data_comments+#], RAX", to_hex(8*(id-1)) )); + APPEND_M(str( "MOV RAX, [track_asm_rax]" )); +#endif if (!jump_to.empty()) { APPEND_M(str( "JMP #", jump_to )); From 4a87a5ebbdcc5c354738abea40ccb4c25ccdd790 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Mon, 16 Feb 2026 19:06:26 -0800 Subject: [PATCH 76/78] ci: fix Linux benchmark clean target and shorten Ubuntu 2weso Use the vdf-client makefile for clean in the addressing benchmark step, and temporarily run short 2weso_test on Ubuntu optimized jobs to reduce CI runtime while preserving coverage elsewhere. Co-authored-by: Cursor --- .github/workflows/test.yaml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 551be645..27055ea9 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -194,7 +194,12 @@ jobs: echo "Running 1weso_test" ./1weso_test echo "Running 2weso_test" - ./2weso_test + if [[ "${{ matrix.os }}" == ubuntu* ]]; then + echo "Using short 2weso_test on Ubuntu" + ./2weso_test 1000 + else + ./2weso_test + fi echo "Running prover_test" if [[ "${{ matrix.os }}" == ubuntu* ]]; then ./prover_test @@ -269,7 +274,7 @@ jobs: local variant="$1" local variant_cppflags="$2" echo "Building variant: ${variant}" - make clean + make -f Makefile.vdf-client clean make optimized=1 -f Makefile.vdf-client CPPFLAGS="${variant_cppflags} ${CPPFLAGS:-}" echo "Benchmarking variant: ${variant}" ./vdf_bench square_asm 2000000 | tee "../bench_${variant}.txt" From 8d0d0d3568c50affdd6d750f8b75af01e022f2f9 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Mon, 16 Feb 2026 19:19:46 -0800 Subject: [PATCH 77/78] ci+asm: revert temporary addressing experiment and restore Linux absolute mode Remove the temporary Ubuntu A/B benchmark workflow changes and reinstate full optimized 2weso coverage, while restoring Linux track_asm accesses to absolute addressing by default. Co-authored-by: Cursor --- .github/workflows/test.yaml | 82 +------------------------------------ src/asm_base.h | 8 +--- 2 files changed, 3 insertions(+), 87 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 27055ea9..fc3bcd37 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -194,12 +194,7 @@ jobs: echo "Running 1weso_test" ./1weso_test echo "Running 2weso_test" - if [[ "${{ matrix.os }}" == ubuntu* ]]; then - echo "Using short 2weso_test on Ubuntu" - ./2weso_test 1000 - else - ./2weso_test - fi + ./2weso_test echo "Running prover_test" if [[ "${{ matrix.os }}" == ubuntu* ]]; then ./prover_test @@ -264,81 +259,6 @@ jobs: echo "Benchmarking vdf_bench with 2,000,000 iterations of square_asm" ./vdf_bench square_asm 2000000 - - name: Benchmark track_asm addressing modes (Ubuntu) - if: matrix.config == 'optimized=1' && matrix.os == 'ubuntu-latest' - run: | - set -euo pipefail - cd src - - run_variant() { - local variant="$1" - local variant_cppflags="$2" - echo "Building variant: ${variant}" - make -f Makefile.vdf-client clean - make optimized=1 -f Makefile.vdf-client CPPFLAGS="${variant_cppflags} ${CPPFLAGS:-}" - echo "Benchmarking variant: ${variant}" - ./vdf_bench square_asm 2000000 | tee "../bench_${variant}.txt" - cp asm_compiled.s "../asm_compiled_${variant}.s" - cp avx2_asm_compiled.s "../avx2_asm_compiled_${variant}.s" - cp avx512_asm_compiled.s "../avx512_asm_compiled_${variant}.s" - } - - run_variant "rip_relative" "-DGENERATE_ASM_TRACKING_DATA=1 -DCHIA_LINUX_USE_ABSOLUTE_TRACK_ASM=0" - run_variant "absolute" "-DGENERATE_ASM_TRACKING_DATA=1 -DCHIA_LINUX_USE_ABSOLUTE_TRACK_ASM=1" - - - name: Summarize track_asm addressing benchmark delta (Ubuntu) - if: matrix.config == 'optimized=1' && matrix.os == 'ubuntu-latest' - run: | - python3 - <<'PY' - import pathlib - import re - import sys - - def parse(path): - text = pathlib.Path(path).read_text(encoding="utf-8", errors="replace") - t = re.search(r"Time:\s*(\d+)\s*ms;", text) - s = re.search(r"speed:\s*([0-9]+(?:\.[0-9]+)?)K\s+ips", text) - if not t or not s: - print(f"Could not parse benchmark output in {path}", file=sys.stderr) - sys.exit(1) - return int(t.group(1)), float(s.group(1)) - - rip_ms, rip_kips = parse("bench_rip_relative.txt") - abs_ms, abs_kips = parse("bench_absolute.txt") - - speed_delta_pct = ((abs_kips - rip_kips) / rip_kips) * 100.0 - time_delta_pct = ((abs_ms - rip_ms) / rip_ms) * 100.0 - - print("track_asm addressing benchmark summary") - print(f" rip_relative: time={rip_ms} ms, speed={rip_kips:.1f}K ips") - print(f" absolute: time={abs_ms} ms, speed={abs_kips:.1f}K ips") - print(f" delta: speed={speed_delta_pct:+.2f}% (absolute vs rip_relative), time={time_delta_pct:+.2f}%") - - summary_path = pathlib.Path(pathlib.os.environ["GITHUB_STEP_SUMMARY"]) - with summary_path.open("a", encoding="utf-8") as f: - f.write("## track_asm addressing benchmark (Ubuntu)\n") - f.write("| variant | time (ms) | speed (K ips) |\n") - f.write("|---|---:|---:|\n") - f.write(f"| rip_relative | {rip_ms} | {rip_kips:.1f} |\n") - f.write(f"| absolute | {abs_ms} | {abs_kips:.1f} |\n") - f.write(f"| delta (absolute vs rip_relative) | {time_delta_pct:+.2f}% time | {speed_delta_pct:+.2f}% speed |\n") - PY - - - name: Upload track_asm addressing benchmark artifacts (Ubuntu) - if: matrix.config == 'optimized=1' && matrix.os == 'ubuntu-latest' - uses: actions/upload-artifact@v4 - with: - name: track-asm-addressing-${{ github.run_id }}-${{ github.run_attempt }} - path: | - bench_rip_relative.txt - bench_absolute.txt - asm_compiled_rip_relative.s - asm_compiled_absolute.s - avx2_asm_compiled_rip_relative.s - avx2_asm_compiled_absolute.s - avx512_asm_compiled_rip_relative.s - avx512_asm_compiled_absolute.s - - name: Benchmark vdf_bench square (Windows) if: matrix.config == 'optimized=1' && startsWith(matrix.os, 'windows') shell: pwsh diff --git a/src/asm_base.h b/src/asm_base.h index 7378c972..0ac58aba 100644 --- a/src/asm_base.h +++ b/src/asm_base.h @@ -79,11 +79,7 @@ string track_asm(string comment, string jump_to = "") { assert(!enable_threads); //this code isn't atomic -#ifndef CHIA_LINUX_USE_ABSOLUTE_TRACK_ASM -#define CHIA_LINUX_USE_ABSOLUTE_TRACK_ASM 0 -#endif - -#if defined(CHIAOSX) || defined(CHIA_WINDOWS) || !CHIA_LINUX_USE_ABSOLUTE_TRACK_ASM +#if defined(CHIAOSX) || defined(CHIA_WINDOWS) APPEND_M(str( "MOV [RIP+track_asm_rax], RAX" )); APPEND_M(str( "MOV RAX, [RIP+asm_tracking_data+#]", to_hex(8*(id-1)) )); APPEND_M(str( "LEA RAX, [RAX+1]" )); @@ -99,7 +95,7 @@ string track_asm(string comment, string jump_to = "") { #else APPEND_M(str( "MOV RAX, OFFSET FLAT:#", comment_label )); #endif -#if defined(CHIAOSX) || defined(CHIA_WINDOWS) || !CHIA_LINUX_USE_ABSOLUTE_TRACK_ASM +#if defined(CHIAOSX) || defined(CHIA_WINDOWS) APPEND_M(str( "MOV [RIP+asm_tracking_data_comments+#], RAX", to_hex(8*(id-1)) )); APPEND_M(str( "MOV RAX, [RIP+track_asm_rax]" )); #else From e42cabd1053fd26517da91516eecff6dde867018 Mon Sep 17 00:00:00 2001 From: Gene Hoffman Date: Tue, 17 Feb 2026 10:46:58 -0800 Subject: [PATCH 78/78] hw-client: link prover_runtime in makefile hw targets Include prover_runtime.o in HW_OBJS for Makefile.vdf-client so emu_hw_test and emu_hw_vdf_client resolve Prover/ParallelProver symbols after the prover header consolidation. Co-authored-by: Cursor --- src/Makefile.vdf-client | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.vdf-client b/src/Makefile.vdf-client index 8a7d7652..24138d96 100644 --- a/src/Makefile.vdf-client +++ b/src/Makefile.vdf-client @@ -90,7 +90,7 @@ avx512_asm_compiled.s: compile_asm compile_asm: compile_asm.o $(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS) -HW_OBJS = $(addprefix hw/,hw_util.o hw_proof.o hw_interface.o chia_driver.o ftdi_driver.o vdf_driver.o pll_freqs.o) vdf_base_hw.o vdf_hw_symbol_anchors.o lzcnt.o +HW_OBJS = $(addprefix hw/,hw_util.o hw_proof.o hw_interface.o chia_driver.o ftdi_driver.o vdf_driver.o pll_freqs.o) vdf_base_hw.o vdf_hw_symbol_anchors.o prover_runtime.o lzcnt.o EMU_OBJS = hw/emu_funcs.o hw/emu_runner.o ifeq ($(OS),Windows_NT) HW_LIB = hw/libft4222/libft4222.lib