From 24157522a8ed2af2a76116ae6258a9b6aad0ffbc Mon Sep 17 00:00:00 2001 From: Alejandro Cabeza Romero Date: Fri, 5 Jun 2026 20:30:56 +0200 Subject: [PATCH] Localise fr to avoid collisions with other libraries. --- .github/resources/witness-generator/Makefile | 10 ++++++---- CONTRIBUTING.md | 8 ++++---- docs/build-pipeline.md | 4 +--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/resources/witness-generator/Makefile b/.github/resources/witness-generator/Makefile index 2acddeb..e06a552 100644 --- a/.github/resources/witness-generator/Makefile +++ b/.github/resources/witness-generator/Makefile @@ -59,8 +59,9 @@ windows: $(BIN) windows-lib: CXXFLAGS=$(PRIORITY_FLAGS) $(CXXFLAGS_COMMON) -fPIC -I/include -Duint="unsigned int" windows-lib: $(LIB) -# Localizes all circuit-specific code to prevent conflicts when multiple circuit -# libraries are linked into the same binary. See CONTRIBUTING.md § "Symbol Isolation". +# Localizes witness-generator implementation symbols to prevent conflicts when multiple circuit libraries are linked +# into the same binary. +# See CONTRIBUTING.md § "Symbol Isolation". PUBLIC_SYMS := $(PROJECT)_generate_witness $(PROJECT)_generate_witness_from_files LOCAL_OBJ := $(PROJECT)_local.o OBJCOPY := $(if $(filter windows,$(OS)),objcopy,llvm-objcopy) @@ -71,9 +72,10 @@ $(BIN): $(COMMON_OBJS) $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ $(LIB): $(LIB_OBJS) - ld -r -o $(LOCAL_OBJ) $(filter-out fr.o,$^) + ld -r -o $(LOCAL_OBJ) $^ $(OBJCOPY) $(foreach sym,$(PUBLIC_SYMS),--keep-global-symbol=$(SYM_PREFIX)$(sym)) $(LOCAL_OBJ) - ar rcs $@ fr.o $(LOCAL_OBJ) + rm -f $@ + ar rcs $@ $(LOCAL_OBJ) rm $(LOCAL_OBJ) %.o: %.cpp $(DEPS_HPP) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ff4349b..3db3747 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -75,11 +75,11 @@ page, which results in a **SIGSEGV**. #### The Fix -The Makefile uses a two-step process to hide all circuit-specific symbols before archiving: +The Makefile uses a two-step process to hide all witness-generator implementation symbols before archiving: -1. **Partial link** (`ld -r`): merges all circuit-specific `.o` files into a single relocatable - object. `fr.o` is excluded — it contains only field arithmetic with no circuit-specific calls - and is safe to deduplicate across circuits. +1. **Partial link** (`ld -r`): merges every witness-generator `.o` file into a single relocatable object. + `fr.o` is included because its `Fr_*` symbols also appear in other native ZK libraries, such as rapidsnark, and must + not leak into the final link. 2. **Symbol localization**: demotes every global symbol to local except the two public FFI entry points (`$(PROJECT)_generate_witness` and `$(PROJECT)_generate_witness_from_files`). Local symbols are invisible to the final linker, so each archive retains a private copy. diff --git a/docs/build-pipeline.md b/docs/build-pipeline.md index a64671b..49caab0 100644 --- a/docs/build-pipeline.md +++ b/docs/build-pipeline.md @@ -89,12 +89,10 @@ with different circuit-specific constants. When multiple circuits are linked int picks one definition per symbol and discards the rest, mixing constants across circuits and corrupting witness generation. -To prevent this, every internal symbol is hidden: circuit objects are merged into a single +To prevent this, every internal symbol is hidden: witness-generator objects are merged into a single relocatable object, then all symbols except the two public entry points are demoted to local. Local symbols are invisible to the final linker, so each circuit keeps its own private copy. -`fr.o` is the exception: it stays global and is added to the archive separately since it doesn't vary between circuits. - See [CONTRIBUTING.md § Symbol Isolation](../CONTRIBUTING.md#symbol-isolation-in-circuit-libraries) for the full explanation and implementation details.