From e1ab69d1b5f75297d362facd27aebcb3ef343dd2 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 26 Mar 2026 18:02:27 +0100 Subject: [PATCH 1/5] Remove Store::addMultipleToStore(Source & source) variant This was used in only one place (the daemon implementation) and it hard-coded a protocol version, so let's get rid of it. --- src/libstore/daemon.cc | 14 ++++++++++++- .../include/nix/store/remote-store.hh | 2 -- src/libstore/include/nix/store/store-api.hh | 2 -- src/libstore/remote-store.cc | 20 +++++++++---------- src/libstore/store-api.cc | 19 ------------------ 5 files changed, 22 insertions(+), 35 deletions(-) diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index 6fa7aa197dd4..d8072b11b2e8 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -515,7 +515,19 @@ static void performOp( logger->startWork(); { FramedSource source(conn.from); - store->addMultipleToStore(source, RepairFlag{repair}, dontCheckSigs ? NoCheckSigs : CheckSigs); + auto expected = readNum(source); + for (uint64_t i = 0; i < expected; ++i) { + auto info = WorkerProto::Serialise::read( + *store, + WorkerProto::ReadConn{ + .from = source, + .version = {.number = {.major = 1, .minor = 16}}, + }); + info.ultimate = false; + EnsureRead wrapper{source, info.narSize}; + store->addToStore(info, wrapper, RepairFlag{repair}, dontCheckSigs ? NoCheckSigs : CheckSigs); + wrapper.finish(); + } } logger->stopWork(); break; diff --git a/src/libstore/include/nix/store/remote-store.hh b/src/libstore/include/nix/store/remote-store.hh index 8c9dc94881c3..289d694aedd3 100644 --- a/src/libstore/include/nix/store/remote-store.hh +++ b/src/libstore/include/nix/store/remote-store.hh @@ -103,8 +103,6 @@ struct RemoteStore : public virtual Store, void addToStore(const ValidPathInfo & info, Source & nar, RepairFlag repair, CheckSigsFlag checkSigs) override; - void addMultipleToStore(Source & source, RepairFlag repair, CheckSigsFlag checkSigs) override; - void addMultipleToStore(PathsSource && pathsToCopy, Activity & act, RepairFlag repair, CheckSigsFlag checkSigs) override; diff --git a/src/libstore/include/nix/store/store-api.hh b/src/libstore/include/nix/store/store-api.hh index 1020c5f9adb5..89dd231a0cf4 100644 --- a/src/libstore/include/nix/store/store-api.hh +++ b/src/libstore/include/nix/store/store-api.hh @@ -571,8 +571,6 @@ public: /** * Import multiple paths into the store. */ - virtual void addMultipleToStore(Source & source, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs); - virtual void addMultipleToStore( PathsSource && pathsToCopy, Activity & act, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs); diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 9d6b9cdaef21..5c3e9323a808 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -469,6 +469,13 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source, Repair void RemoteStore::addMultipleToStore( PathsSource && pathsToCopy, Activity & act, RepairFlag repair, CheckSigsFlag checkSigs) { + if (getConnection()->protoVersion < WorkerProto::Version{.number = {1, 32}}) { + Store::addMultipleToStore(std::move(pathsToCopy), act, repair, checkSigs); + return; + } + + auto conn(getConnection()); + // `addMultipleToStore` is single threaded size_t bytesExpected = 0; for (auto & [pathInfo, _] : pathsToCopy) { @@ -497,17 +504,8 @@ void RemoteStore::addMultipleToStore( } }); - addMultipleToStore(*source, repair, checkSigs); -} - -void RemoteStore::addMultipleToStore(Source & source, RepairFlag repair, CheckSigsFlag checkSigs) -{ - if (getConnection()->protoVersion >= WorkerProto::Version{.number = {1, 32}}) { - auto conn(getConnection()); - conn->to << WorkerProto::Op::AddMultipleToStore << repair << !checkSigs; - conn.withFramedSink([&](Sink & sink) { source.drainInto(sink); }); - } else - Store::addMultipleToStore(source, repair, checkSigs); + conn->to << WorkerProto::Op::AddMultipleToStore << repair << !checkSigs; + conn.withFramedSink([&](Sink & sink) { source->drainInto(sink); }); } void RemoteStore::registerDrvOutput(const Realisation & info) diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 806038134be6..06a3a052371f 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -224,25 +224,6 @@ void Store::addMultipleToStore(PathsSource && pathsToCopy, Activity & act, Repai }); } -void Store::addMultipleToStore(Source & source, RepairFlag repair, CheckSigsFlag checkSigs) -{ - auto expected = readNum(source); - for (uint64_t i = 0; i < expected; ++i) { - // FIXME we should not be using the worker protocol here, let - // alone the worker protocol with a hard-coded version! - auto info = WorkerProto::Serialise::read( - *this, - WorkerProto::ReadConn{ - .from = source, - .version = {.number = {.major = 1, .minor = 16}}, - }); - info.ultimate = false; - EnsureRead wrapper{source, info.narSize}; - addToStore(info, wrapper, repair, checkSigs); - wrapper.finish(); - } -} - /* The aim of this function is to compute in one pass the correct ValidPathInfo for the files that we are trying to add to the store. To accomplish that in one From 9f67f7e15e6ab2d76e825834de01ea6c43c937ca Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 26 Mar 2026 18:57:38 +0100 Subject: [PATCH 2/5] Remove unnecessary #include --- src/libstore/store-api.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 06a3a052371f..57952b1dfd4a 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -14,9 +14,6 @@ #include "nix/util/callback.hh" #include "nix/util/git.hh" #include "nix/util/posix-source-accessor.hh" -// FIXME this should not be here, see TODO below on -// `addMultipleToStore`. -#include "nix/store/worker-protocol.hh" #include "nix/util/signals.hh" #include "nix/util/environment-variables.hh" #include "nix/util/file-system.hh" From c23b2fe9c104a946390fa5a721fefef580db3d82 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 26 Mar 2026 18:39:08 +0100 Subject: [PATCH 3/5] Add a feature to make RemoteStore::addMultipleToStore() respect the proto version --- src/libstore/daemon.cc | 4 +++- src/libstore/include/nix/store/worker-protocol.hh | 1 + src/libstore/remote-store.cc | 4 +++- src/libstore/worker-protocol.cc | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index d8072b11b2e8..31a82b40421d 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -521,7 +521,9 @@ static void performOp( *store, WorkerProto::ReadConn{ .from = source, - .version = {.number = {.major = 1, .minor = 16}}, + .version = conn.protoVersion.features.contains(WorkerProto::featureVersionedAddToStoreMultiple) + ? conn.protoVersion + : WorkerProto::Version{.number = {.major = 1, .minor = 16}}, }); info.ultimate = false; EnsureRead wrapper{source, info.narSize}; diff --git a/src/libstore/include/nix/store/worker-protocol.hh b/src/libstore/include/nix/store/worker-protocol.hh index 7ce215ca63a4..977ce870c1cf 100644 --- a/src/libstore/include/nix/store/worker-protocol.hh +++ b/src/libstore/include/nix/store/worker-protocol.hh @@ -111,6 +111,7 @@ struct WorkerProto static constexpr std::string_view featureQueryActiveBuilds = "queryActiveBuilds"; static constexpr std::string_view featureProvenance = "provenance"; + static constexpr std::string_view featureVersionedAddToStoreMultiple = "versionedAddToStoreMultiple"; /** * A unidirectional read connection, to be used by the read half of the diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 5c3e9323a808..3af877bf1776 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -496,7 +496,9 @@ void RemoteStore::addMultipleToStore( *this, WorkerProto::WriteConn{ .to = sink, - .version = {.number = {.major = 1, .minor = 16}}, + .version = conn->protoVersion.features.contains(WorkerProto::featureVersionedAddToStoreMultiple) + ? conn->protoVersion + : WorkerProto::Version{.number = {.major = 1, .minor = 16}}, }, pathInfo); pathSource->drainInto(sink); diff --git a/src/libstore/worker-protocol.cc b/src/libstore/worker-protocol.cc index a0d126ff8c8e..c1474304c4c9 100644 --- a/src/libstore/worker-protocol.cc +++ b/src/libstore/worker-protocol.cc @@ -25,6 +25,7 @@ const WorkerProto::Version WorkerProto::latest = { { std::string{WorkerProto::featureQueryActiveBuilds}, std::string{WorkerProto::featureProvenance}, + std::string{WorkerProto::featureVersionedAddToStoreMultiple}, }, }; From 4934dbb16a59d3129b2a11b432334f273d93bd0f Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 26 Mar 2026 18:46:20 +0100 Subject: [PATCH 4/5] Remove redundant provenance field from {Read,Write}Conn This makes `nix copy` from ssh-ng to the daemon preserve provenance, because in combination with the previous commits, RemoteStore::addToStoreMultiple() now sends provenance if the daemon supports it. Fixes https://github.com/DeterminateSystems/nix-src/issues/369. --- src/libstore/include/nix/store/worker-protocol-connection.hh | 2 -- src/libstore/include/nix/store/worker-protocol.hh | 2 -- src/libstore/worker-protocol.cc | 4 ++-- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/libstore/include/nix/store/worker-protocol-connection.hh b/src/libstore/include/nix/store/worker-protocol-connection.hh index d224710a9d4e..49de3fe67396 100644 --- a/src/libstore/include/nix/store/worker-protocol-connection.hh +++ b/src/libstore/include/nix/store/worker-protocol-connection.hh @@ -36,7 +36,6 @@ struct WorkerProto::BasicConnection return WorkerProto::ReadConn{ .from = from, .version = protoVersion, - .provenance = protoVersion.features.contains(WorkerProto::featureProvenance), }; } @@ -53,7 +52,6 @@ struct WorkerProto::BasicConnection return WorkerProto::WriteConn{ .to = to, .version = protoVersion, - .provenance = protoVersion.features.contains(WorkerProto::featureProvenance), }; } }; diff --git a/src/libstore/include/nix/store/worker-protocol.hh b/src/libstore/include/nix/store/worker-protocol.hh index 977ce870c1cf..7c205016b7e5 100644 --- a/src/libstore/include/nix/store/worker-protocol.hh +++ b/src/libstore/include/nix/store/worker-protocol.hh @@ -122,7 +122,6 @@ struct WorkerProto Source & from; const Version & version; bool shortStorePaths = false; - bool provenance = false; }; /** @@ -134,7 +133,6 @@ struct WorkerProto Sink & to; const Version & version; bool shortStorePaths = false; - bool provenance = false; }; /** diff --git a/src/libstore/worker-protocol.cc b/src/libstore/worker-protocol.cc index c1474304c4c9..3c7acbfb4784 100644 --- a/src/libstore/worker-protocol.cc +++ b/src/libstore/worker-protocol.cc @@ -353,7 +353,7 @@ UnkeyedValidPathInfo WorkerProto::Serialise::read(const St info.sigs = WorkerProto::Serialise>::read(store, conn); info.ca = ContentAddress::parseOpt(readString(conn.from)); } - if (conn.provenance) + if (conn.version.features.contains(WorkerProto::featureProvenance)) info.provenance = Provenance::from_json_str_optional(readString(conn.from)); return info; } @@ -370,7 +370,7 @@ void WorkerProto::Serialise::write( WorkerProto::write(store, conn, pathInfo.sigs); conn.to << renderContentAddress(pathInfo.ca); } - if (conn.provenance) + if (conn.version.features.contains(WorkerProto::featureProvenance)) conn.to << (pathInfo.provenance ? pathInfo.provenance->to_json_str() : ""); } From f0ae44e5048aaefeb2c90b10206397afa468a6a8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 24 Apr 2026 18:14:10 +0200 Subject: [PATCH 5/5] RemoteStore::addToStore(): Fix version comparison --- src/libstore/remote-store.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 3af877bf1776..bf03b24fdf99 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -469,7 +469,7 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source, Repair void RemoteStore::addMultipleToStore( PathsSource && pathsToCopy, Activity & act, RepairFlag repair, CheckSigsFlag checkSigs) { - if (getConnection()->protoVersion < WorkerProto::Version{.number = {1, 32}}) { + if (getConnection()->protoVersion.number < WorkerProto::Version::Number{1, 32}) { Store::addMultipleToStore(std::move(pathsToCopy), act, repair, checkSigs); return; }