Skip to content

Commit 86baa21

Browse files
committed
Add experimental feature to enable provenance
1 parent 6addb78 commit 86baa21

File tree

7 files changed

+47
-22
lines changed

7 files changed

+47
-22
lines changed

src/libstore/daemon.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1047,8 +1047,12 @@ void processConnection(ref<Store> store, FdSource && from, FdSink && to, Trusted
10471047
#endif
10481048

10491049
/* Exchange the greeting. */
1050+
auto myFeatures = WorkerProto::allFeatures;
1051+
if (!experimentalFeatureSettings.isEnabled(Xp::Provenance))
1052+
myFeatures.erase(std::string(WorkerProto::featureProvenance));
1053+
10501054
auto [protoVersion, features] =
1051-
WorkerProto::BasicServerConnection::handshake(to, from, PROTOCOL_VERSION, WorkerProto::allFeatures);
1055+
WorkerProto::BasicServerConnection::handshake(to, from, PROTOCOL_VERSION, myFeatures);
10521056

10531057
if (protoVersion < MINIMUM_PROTOCOL_VERSION)
10541058
throw Error("the Nix client version is too old");

src/libstore/local-store.cc

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -337,13 +337,16 @@ LocalStore::LocalStore(ref<const Config> config)
337337
/* Prepare SQL statements. */
338338
state->stmts->RegisterValidPath.create(
339339
state->db,
340-
"insert into ValidPaths (path, hash, registrationTime, deriver, narSize, ultimate, sigs, ca, provenance) values (?, ?, ?, ?, ?, ?, ?, ?, ?);");
340+
fmt("insert into ValidPaths (path, hash, registrationTime, deriver, narSize, ultimate, sigs, ca%s) values (?, ?, ?, ?, ?, ?, ?, ?%s);",
341+
experimentalFeatureSettings.isEnabled(Xp::Provenance) ? ", provenance" : "",
342+
experimentalFeatureSettings.isEnabled(Xp::Provenance) ? ", ?" : ""));
341343
state->stmts->UpdatePathInfo.create(
342344
state->db, "update ValidPaths set narSize = ?, hash = ?, ultimate = ?, sigs = ?, ca = ? where path = ?;");
343345
state->stmts->AddReference.create(state->db, "insert or replace into Refs (referrer, reference) values (?, ?);");
344346
state->stmts->QueryPathInfo.create(
345347
state->db,
346-
"select id, hash, registrationTime, deriver, narSize, ultimate, sigs, ca, provenance from ValidPaths where path = ?;");
348+
fmt("select id, hash, registrationTime, deriver, narSize, ultimate, sigs, ca%s from ValidPaths where path = ?;",
349+
experimentalFeatureSettings.isEnabled(Xp::Provenance) ? ", provenance" : ""));
347350
state->stmts->QueryReferences.create(
348351
state->db, "select path from Refs join ValidPaths on reference = id where referrer = ?;");
349352
state->stmts->QueryReferrers.create(
@@ -599,7 +602,8 @@ void LocalStore::upgradeDBSchema(State & state)
599602
#include "ca-specific-schema.sql.gen.hh"
600603
);
601604

602-
doUpgrade("20241024-provenance", "alter table ValidPaths add column provenance text");
605+
if (experimentalFeatureSettings.isEnabled(Xp::Provenance))
606+
doUpgrade("20241024-provenance", "alter table ValidPaths add column provenance text");
603607
}
604608

605609
/* To improve purity, users may want to make the Nix store a read-only
@@ -695,14 +699,14 @@ uint64_t LocalStore::addValidPath(State & state, const ValidPathInfo & info, boo
695699
"cannot add path '%s' to the Nix store because it claims to be content-addressed but isn't",
696700
printStorePath(info.path));
697701

698-
state.stmts->RegisterValidPath
699-
.use()(printStorePath(info.path))(info.narHash.to_string(HashFormat::Base16, true))(
700-
info.registrationTime == 0 ? time(0) : info.registrationTime)(
701-
info.deriver ? printStorePath(*info.deriver) : "",
702-
(bool) info.deriver)(info.narSize, info.narSize != 0)(info.ultimate ? 1 : 0, info.ultimate)(
703-
concatStringsSep(" ", info.sigs), !info.sigs.empty())(renderContentAddress(info.ca), (bool) info.ca)(
704-
info.provenance ? info.provenance->to_json_str() : "", (bool) info.provenance)
705-
.exec();
702+
auto query = state.stmts->RegisterValidPath.use()(printStorePath(info.path))(
703+
info.narHash.to_string(HashFormat::Base16, true))(info.registrationTime == 0 ? time(0) : info.registrationTime)(
704+
info.deriver ? printStorePath(*info.deriver) : "",
705+
(bool) info.deriver)(info.narSize, info.narSize != 0)(info.ultimate ? 1 : 0, info.ultimate)(
706+
concatStringsSep(" ", info.sigs), !info.sigs.empty())(renderContentAddress(info.ca), (bool) info.ca);
707+
if (experimentalFeatureSettings.isEnabled(Xp::Provenance))
708+
query(info.provenance ? info.provenance->to_json_str() : "", (bool) info.provenance);
709+
query.exec();
706710
uint64_t id = state.db.getLastInsertedRowId();
707711

708712
/* If this is a derivation, then store the derivation outputs in
@@ -792,9 +796,11 @@ std::shared_ptr<const ValidPathInfo> LocalStore::queryPathInfoInternal(State & s
792796
while (useQueryReferences.next())
793797
info->references.insert(parseStorePath(useQueryReferences.getStr(0)));
794798

795-
auto prov = (const char *) sqlite3_column_text(state.stmts->QueryPathInfo, 8);
796-
if (prov)
797-
info->provenance = Provenance::from_json_str(prov);
799+
if (experimentalFeatureSettings.isEnabled(Xp::Provenance)) {
800+
auto prov = (const char *) sqlite3_column_text(state.stmts->QueryPathInfo, 8);
801+
if (prov)
802+
info->provenance = Provenance::from_json_str(prov);
803+
}
798804

799805
return info;
800806
}

src/libstore/nar-info.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ NarInfo::NarInfo(const StoreDirConfig & store, const std::string & s, const std:
8585
throw corrupt("extra CA");
8686
// FIXME: allow blank ca or require skipping field?
8787
ca = ContentAddress::parseOpt(value);
88-
} else if (name == "Provenance")
88+
} else if (name == "Provenance" && experimentalFeatureSettings.isEnabled(Xp::Provenance))
8989
provenance = Provenance::from_json_str(value);
9090

9191
pos = eol + 1;

src/libstore/path-info.cc

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,8 @@ UnkeyedValidPathInfo::toJSON(const StoreDirConfig * store, bool includeImpureInf
216216
for (auto & sig : sigs)
217217
sigsObj.push_back(sig);
218218

219-
jsonObject["provenance"] = provenance ? provenance->to_json() : nullptr;
219+
if (experimentalFeatureSettings.isEnabled(Xp::Provenance))
220+
jsonObject["provenance"] = provenance ? provenance->to_json() : nullptr;
220221
}
221222

222223
return jsonObject;
@@ -292,9 +293,11 @@ UnkeyedValidPathInfo UnkeyedValidPathInfo::fromJSON(const StoreDirConfig * store
292293
if (auto * rawSignatures = optionalValueAt(json, "signatures"))
293294
res.sigs = getStringSet(*rawSignatures);
294295

295-
auto prov = json.find("provenance");
296-
if (prov != json.end() && !prov->second.is_null())
297-
res.provenance = Provenance::from_json(prov->second);
296+
if (experimentalFeatureSettings.isEnabled(Xp::Provenance)) {
297+
auto prov = json.find("provenance");
298+
if (prov != json.end() && !prov->second.is_null())
299+
res.provenance = Provenance::from_json(prov->second);
300+
}
298301

299302
return res;
300303
}

src/libstore/remote-store.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,11 @@ void RemoteStore::initConnection(Connection & conn)
7272
StringSink saved;
7373
TeeSource tee(conn.from, saved);
7474
try {
75+
auto myFeatures = WorkerProto::allFeatures;
76+
if (!experimentalFeatureSettings.isEnabled(Xp::Provenance))
77+
myFeatures.erase(std::string(WorkerProto::featureProvenance));
7578
auto [protoVersion, features] =
76-
WorkerProto::BasicClientConnection::handshake(conn.to, tee, PROTOCOL_VERSION, WorkerProto::allFeatures);
79+
WorkerProto::BasicClientConnection::handshake(conn.to, tee, PROTOCOL_VERSION, myFeatures);
7780
if (protoVersion < MINIMUM_PROTOCOL_VERSION)
7881
throw Error("the Nix daemon version is too old");
7982
conn.protoVersion = protoVersion;

src/libutil/experimental-features.cc

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ struct ExperimentalFeatureDetails
2525
* feature, we either have no issue at all if few features are not added
2626
* at the end of the list, or a proper merge conflict if they are.
2727
*/
28-
constexpr size_t numXpFeatures = 1 + static_cast<size_t>(Xp::ParallelEval);
28+
constexpr size_t numXpFeatures = 1 + static_cast<size_t>(Xp::Provenance);
2929

3030
constexpr std::array<ExperimentalFeatureDetails, numXpFeatures> xpFeatureDetails = {{
3131
{
@@ -320,6 +320,14 @@ constexpr std::array<ExperimentalFeatureDetails, numXpFeatures> xpFeatureDetails
320320
)",
321321
.trackingUrl = "",
322322
},
323+
{
324+
.tag = Xp::Provenance,
325+
.name = "provenance",
326+
.description = R"(
327+
Enable keeping track of the provenance of store paths.
328+
)",
329+
.trackingUrl = "",
330+
},
323331
}};
324332

325333
static_assert(

src/libutil/include/nix/util/experimental-features.hh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ enum struct ExperimentalFeature {
3939
BLAKE3Hashes,
4040
BuildTimeFetchTree,
4141
ParallelEval,
42+
Provenance,
4243
};
4344

4445
extern std::set<std::string> stabilizedFeatures;

0 commit comments

Comments
 (0)