What changed, and why it matters
This commit updates Monero's Guix reproducible-build scripts to add support for Rust dependencies needed by an upcoming feature called FCMP++. It does not change wallet logic, consensus rules, or network code. The changes are build-system plumbing: vendoring Rust crates, configuring Cargo to use them offline, and exposing the Rust standard library source. There is no direct evidence this commit fixes or introduces a security vulnerability.
Treat as routine build-system maintenance. Reviewers should verify that the pinned git revisions and vendored dependency hashes match the intended upstream sources, and that the RUSTC_BOOTSTRAP usage remains confined to the Guix build environment. No immediate security response is indicated.
Security signals we found
RUSTC_BOOTSTRAP=1 enables nightly-only compiler features on stable Rust, which is a known anti-pattern but here is used only inside the deterministic Guix build container
Cargo vendoring includes two git dependencies (crypto-bigint fork and monero-oxide), but their exact revisions are pinned in config.toml
The rust dependency archive hash is hard-coded and verified against the Guix store item, improving supply-chain reproducibility
No runtime, consensus, or cryptographic code is changed in this commit
Evidence from the diff
The patch modifies contrib/guix build scripts to: (1) vendor Rust dependencies for src/fcmp_pp/fcmp_pp_rust and archive them deterministically; (2) add a rust-std Guix package that unpacks the Rust source tarball; (3) configure Cargo with a vendored-sources config.toml and -Zbuild-std=std,panic_abort; (4) set RUSTC_BOOTSTRAP=1 and __CARGO_TESTS_ONLY_SRC_ROOT to enable building the standard library on stable Rust; and (5) adjust LD_LIBRARY_PATH and GCC library discovery. The commit is preparatory infrastructure for FCMP++ and is gated behind commented placeholders referencing a future PR (#10359).
Changed components
contrib/guix/guix-buildcontrib/guix/libexec/build.shcontrib/guix/manifest.scmcontrib/guix/rust/cargo.scmcontrib/guix/rust/cargo.shcontrib/guix/rust/config.tomlInspect captured patch +184 / −2
diff --git a/contrib/guix/guix-build b/contrib/guix/guix-build
index 9d61133..a99c0d5 100755
--- a/contrib/guix/guix-build
+++ b/contrib/guix/guix-build
@@ -270,6 +270,40 @@ mkdir -p "$OUTDIR_BASE"
LOGDIR_BASE="${LOGDIR_BASE:-${VERSION_BASE}/logs}"
mkdir -p "$LOGDIR_BASE"
+# Download and archive Rust dependencies.
+# When Cargo.lock is updated: increment RUST_DEPS_VERSION, update
+# RUST_DEPS_HASH with the hash reported below, and update
+# contrib/guix/rust/config.toml if the set of git sources changed
+RUST_DEPS_VERSION=0
+RUST_DEPS_HASH="gg5izydrra2b1ywgskvlrfrh983gf6b4"
+RUST_DEPS_ARCHIVE="rust_deps-${RUST_DEPS_VERSION}.tar.gz"
+#UNCOMMENT_IN_10359# RUST_DEPS_STORE_ITEM="/gnu/store/${RUST_DEPS_HASH}-${RUST_DEPS_ARCHIVE}"
+#UNCOMMENT_IN_10359# if [ ! -f "${RUST_DEPS_STORE_ITEM}" ]; then
+if false; then #REMOVE_IN_10359#
+ time-machine environment --manifest="${PWD}/contrib/guix/rust/cargo.scm" \
+ --container \
+ --pure \
+ --network \
+ --no-cwd \
+ --writable-root \
+ --share="$PWD"=/monero \
+ -- env RUST_DEPS_ARCHIVE="$RUST_DEPS_ARCHIVE" \
+ bash /monero/contrib/guix/rust/cargo.sh
+
+ RUST_DEPS_ADDED_ITEM="$(time-machine download "${RUST_DEPS_ARCHIVE}" | grep --max-count=1 '^/gnu/store/')"
+ rm ${RUST_DEPS_ARCHIVE}
+
+ if [ "${RUST_DEPS_ADDED_ITEM}" != "${RUST_DEPS_STORE_ITEM}" ]; then
+ cat << EOF
+ERR: The vendored Rust dependencies do not hash to the expected store item.
+
+ expected: ${RUST_DEPS_STORE_ITEM}
+ actual: ${RUST_DEPS_ADDED_ITEM}
+EOF
+ exit 1
+ fi
+fi
+
# Download the depends sources now as we won't have internet access in the build
# container
for host in $HOSTS; do
@@ -450,6 +484,7 @@ EOF
--share="$DISTSRC_BASE"=/distsrc-base \
--share="$OUTDIR_BASE"=/outdir-base \
--share="$LOGDIR_BASE"=/logdir-base \
+ ${RUST_DEPS_STORE_ITEM:+--expose="$RUST_DEPS_STORE_ITEM"=/rust-deps} \
--expose="$(git rev-parse --git-common-dir)" \
${SOURCES_PATH:+--share="$SOURCES_PATH"} \
${BASE_CACHE:+--share="$BASE_CACHE"} \
diff --git a/contrib/guix/libexec/build.sh b/contrib/guix/libexec/build.sh
index 5c4f58f..eb3b864 100644
--- a/contrib/guix/libexec/build.sh
+++ b/contrib/guix/libexec/build.sh
@@ -85,6 +85,10 @@ unset OBJCPLUS_INCLUDE_PATH
NATIVE_GCC="$(store_path gcc-toolchain)"
+NATIVE_GCC_VERSION="${NATIVE_GCC##*-gcc-toolchain-}"
+NATIVE_GCC_VERSION="${NATIVE_GCC_VERSION%%-*}"
+NATIVE_GCC_LIB="$(find /gnu/store -maxdepth 1 -name "*-gcc-${NATIVE_GCC_VERSION}-lib" | sort | head -n 1)"
+
export C_INCLUDE_PATH="${NATIVE_GCC}/include"
export CPLUS_INCLUDE_PATH="${NATIVE_GCC}/include/c++:${NATIVE_GCC}/include"
export OBJC_INCLUDE_PATH="${NATIVE_GCC}/include"
@@ -132,7 +136,7 @@ case "$HOST" in
# See depends/hosts/darwin.mk for more details.
;;
*android*)
- export LD_LIBRARY_PATH="$(find /gnu/store -maxdepth 1 -name "*zlib*" | sort | head -n 1)/lib:$(find /gnu/store -maxdepth 1 -name "*gcc-14*-lib" | sort | head -n 1)/lib"
+ export LD_LIBRARY_PATH="$(find /gnu/store -maxdepth 1 -name "*zlib*" | sort | head -n 1)/lib:${NATIVE_GCC_LIB}/lib"
;;
*linux-gnu*)
CROSS_GLIBC="$(store_path "glibc-cross-${HOST}")"
@@ -301,6 +305,31 @@ case "$HOST" in
*mingw*) HOST_LDFLAGS="-Wl,--no-insert-timestamp" ;;
esac
+LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+${LD_LIBRARY_PATH}:}${NATIVE_GCC_LIB}/lib"
+
+RUST_STD="$(store_path rust-std)"
+
+# error: "/gnu/store/<...>-rust-1.82.0/lib/rustlib/src/rust/library/Cargo.lock" does not exist,
+# unable to build with the standard library
+#
+# The standard library does not exist at the location Cargo expects.
+#
+# We can override the path to the Rust source by setting the __CARGO_TESTS_ONLY_SRC_ROOT environment variable.
+# See: https://github.com/rust-lang/cargo/blob/rust-1.82.0/src/cargo/core/compiler/standard_lib.rs#L183
+export __CARGO_TESTS_ONLY_SRC_ROOT="${RUST_STD}/library"
+
+# error: the `-Z` flag is only accepted on the nightly channel of Cargo, but this is the `stable` channel
+#
+# Since we don't have access to the nightly channel, we need to bypass the check with RUSTC_BOOTSTRAP.
+#
+# We could avoid using `-Z build-std` by cross-compiling the full standard library for each target. This approach
+# adds hours to our build time and greatly increases the amount of foreign source code that is compiled as part of
+# our build process.
+export RUSTC_BOOTSTRAP=1
+
+# See: https://rust-lang.github.io/rust-project-goals/2025h1/build-std.html
+CARGO_OPTIONS="-Zbuild-std=std,panic_abort;"
+
export GIT_DISCOVERY_ACROSS_FILESYSTEM=1
# Force Trezor support for release binaries
export USE_DEVICE_TREZOR_MANDATORY=1
@@ -338,6 +367,23 @@ mkdir -p "$DISTSRC"
# Turn off unused default options
CMAKEFLAGS+=" -DCOMPILER_CACHE=none -DBUILD_DOCUMENTATION=OFF"
+ # Make sure cargo knows where to find the vendored sources.
+ mkdir -p "${HOME}/.cargo"
+ cp contrib/guix/rust/config.toml "${HOME}/.cargo/"
+
+ # Unpack rust dependencies
+ mkdir -p /rust/vendor
+ #UNCOMMENT_IN_10359# tar xf /rust-deps -C /rust
+
+ # "vendor" rust std
+ for dir in "${RUST_STD}"/vendor/*/; do
+ [ -d "$dir" ] || continue
+ BN=$(basename "$dir")
+ if [ ! -d "/rust/vendor/$BN" ]; then
+ ln -s "$dir" "/rust/vendor/$BN"
+ fi
+ done
+
# Configure this DISTSRC for $HOST
# shellcheck disable=SC2086
env CFLAGS="${HOST_CFLAGS}" CXXFLAGS="${HOST_CXXFLAGS}" \
@@ -345,9 +391,10 @@ mkdir -p "$DISTSRC"
-DCMAKE_INSTALL_PREFIX="${INSTALLPATH}" \
-DCMAKE_EXE_LINKER_FLAGS="${HOST_LDFLAGS}" \
-DCMAKE_SHARED_LINKER_FLAGS="${HOST_LDFLAGS}" \
+ -DCARGO_OPTIONS="${CARGO_OPTIONS}" \
${CMAKEFLAGS}
- make -C build --jobs="$JOBS"
+ LD_LIBRARY_PATH="${LD_LIBRARY_PATH}" make -C build --jobs="$JOBS"
# Copy docs
cp README.md LICENSE docs/ANONYMITY_NETWORKS.md "${INSTALLPATH}"
diff --git a/contrib/guix/manifest.scm b/contrib/guix/manifest.scm
index b9b7909..2a3badd 100644
--- a/contrib/guix/manifest.scm
+++ b/contrib/guix/manifest.scm
@@ -214,6 +214,36 @@ chain for " target " development."))
(delete "make")
(append gnu-make-4.2))))) ;; make >= 4.4 causes an infinite loop (stdio-common)
+(define-public rust-std
+ (package
+ (name "rust-std")
+ (version (package-version rust))
+ ;; You'd expect (source (package-source (rust)) to work here,
+ ;; but it refers to the source store item and NOT the .tar.gz archive
+ (source (origin
+ (method url-fetch)
+ (uri (origin-uri (package-source rust)))
+ (sha256
+ (content-hash-value (origin-hash (package-source rust))))))
+ (build-system trivial-build-system)
+ (native-inputs (list tar gzip))
+ (arguments
+ `(#:modules ((guix build utils))
+ #:builder
+ (begin
+ (use-modules (guix build utils))
+ (let ((out (assoc-ref %outputs "out"))
+ (source (assoc-ref %build-inputs "source"))
+ (tar (search-input-file %build-inputs "/bin/tar"))
+ (gzip (search-input-file %build-inputs "/bin/gzip"))
+ (gzip-path (string-append (assoc-ref %build-inputs "gzip") "/bin")))
+ (setenv "PATH" gzip-path)
+ (mkdir out)
+ (invoke tar "xvf" source "-C" out "--strip-components=1")))))
+ (synopsis (package-synopsis rust))
+ (description (package-description rust))
+ (home-page (package-home-page rust))
+ (license (package-license rust))))
; This list declares which packages are included in the container environment. It
; should reflect the minimal set of packages we need to build and debug the build
@@ -262,6 +292,7 @@ chain for " target " development."))
cmake-minimal
rust
(list rust "cargo")
+ rust-std
;; Scripting
perl ; required to build openssl in depends
diff --git a/contrib/guix/rust/cargo.scm b/contrib/guix/rust/cargo.scm
new file mode 100644
index 0000000..a8e62d9
--- /dev/null
+++ b/contrib/guix/rust/cargo.scm
@@ -0,0 +1,26 @@
+(use-modules ((gnu packages base) #:select (coreutils-minimal diffutils findutils tar))
+ ((gnu packages bash) #:select (bash-minimal))
+ ((gnu packages compression) #:select (gzip))
+ ((gnu packages curl) #:select (curl))
+ ((gnu packages nss) #:select (nss-certs))
+ ((gnu packages rust) #:select (rust)))
+
+(packages->manifest
+ (append
+ (list
+ ;; The Basics
+ bash-minimal
+ coreutils-minimal
+
+ ;; File(system) inspection
+ findutils ;; find
+ diffutils ;; diff
+
+ ;; Cargo
+ (list rust "cargo")
+ curl ;; networking
+ nss-certs ;; idem
+
+ ;; Compression
+ gzip
+ tar)))
diff --git a/contrib/guix/rust/cargo.sh b/contrib/guix/rust/cargo.sh
new file mode 100644
index 0000000..9dc4978
--- /dev/null
+++ b/contrib/guix/rust/cargo.sh
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+set -e -o pipefail
+
+# Environment variables for determinism
+export LC_ALL=C
+export SOURCE_DATE_EPOCH=1397818193
+export TAR_OPTIONS="--owner=0 --group=0 --numeric-owner --mtime='@${SOURCE_DATE_EPOCH}' --sort=name"
+export TZ="UTC"
+umask 0022
+
+# Vendor fcmp_pp_rust deps
+echo "Fetching rust dependencies.."
+cd /monero/src/fcmp_pp/fcmp_pp_rust
+cargo vendor --locked /rust/vendor > /tmp/config.toml
+
+if ! diff --unified /monero/contrib/guix/rust/config.toml /tmp/config.toml; then
+ echo ""
+ echo "ERR: contrib/guix/rust/config.toml does not match the configuration"
+ echo " required by Cargo.lock. Update it as shown in the diff above."
+ exit 1
+fi
+
+# Create deterministic archive
+cd /rust
+find . -print0 \
+ | sort --zero-terminated \
+ | tar --create --no-recursion --mode='u+rw,go+r-w,a+X' --null --files-from=- \
+ | gzip -9n > "/monero/$RUST_DEPS_ARCHIVE"
diff --git a/contrib/guix/rust/config.toml b/contrib/guix/rust/config.toml
new file mode 100644
index 0000000..53d446d
--- /dev/null
+++ b/contrib/guix/rust/config.toml
@@ -0,0 +1,15 @@
+[source.crates-io]
+replace-with = "vendored-sources"
+
+[source."git+https://github.com/kayabaNerve/crypto-bigint?branch=c-repr"]
+git = "https://github.com/kayabaNerve/crypto-bigint"
+branch = "c-repr"
+replace-with = "vendored-sources"
+
+[source."git+https://github.com/monero-oxide/monero-oxide?rev=71da8f03a87f596db674258cda74553068a57bcd"]
+git = "https://github.com/monero-oxide/monero-oxide"
+rev = "71da8f03a87f596db674258cda74553068a57bcd"
+replace-with = "vendored-sources"
+
+[source.vendored-sources]
+directory = "/rust/vendor"
Why this scored 18/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.