Skip to content

Commit

Permalink
rename "nonce" to "fingerprint"
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewrk committed Feb 26, 2025
1 parent 67904e9 commit de43f5e
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 38 deletions.
2 changes: 1 addition & 1 deletion build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@
},
},
.paths = .{""},
.nonce = 0xc1ce108124179e16,
.fingerprint = 0xc1ce108124179e16,
}
10 changes: 5 additions & 5 deletions doc/build.zig.zon.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,24 @@ Zig package namespace.

Must be a valid bare Zig identifier (don't `@` me), limited to 32 bytes.

Together with `nonce`, this represents a globally unique package identifier.
Together with `fingerprint`, this represents a globally unique package identifier.

### `nonce`
### `fingerprint`

Together with `name`, this represents a globally unique package identifier. This
field is auto-initialized by the toolchain when the package is first created,
and then *never changes*. This allows Zig to unambiguously detect when one
package is an updated version of another.

When forking a Zig project, this nonce should be regenerated if the upstream
When forking a Zig project, this fingerprint should be regenerated if the upstream
project is still maintained. Otherwise, the fork is *hostile*, attempting to
take control over the original project's identity. The nonce can be regenerated
take control over the original project's identity. The fingerprint can be regenerated
by deleting the field and running `zig build`.

This 64-bit integer is the combination of a 32-bit id component and a 32-bit
checksum.

The id component within the nonce has these restrictions:
The id component within the fingerprint has these restrictions:

`0x00000000` is reserved for legacy packages.

Expand Down
2 changes: 1 addition & 1 deletion lib/init/build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
// original project's identity. Thus it is recommended to leave the comment
// on the following line intact, so that it shows up in code reviews that
// modify the field.
.nonce = .NONCE, // Changing this has security and trust implications.
.fingerprint = .FINGERPRINT, // Changing this has security and trust implications.

// Tracks the earliest Zig version that the package considers to be a
// supported use case.
Expand Down
8 changes: 4 additions & 4 deletions src/Package.zig
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,25 @@ pub const multihash_len = 1 + 1 + Hash.Algo.digest_length;
pub const multihash_hex_digest_len = 2 * multihash_len;
pub const MultiHashHexDigest = [multihash_hex_digest_len]u8;

pub const Nonce = packed struct(u64) {
pub const Fingerprint = packed struct(u64) {
id: u32,
checksum: u32,

pub fn generate(name: []const u8) Nonce {
pub fn generate(name: []const u8) Fingerprint {
return .{
.id = std.crypto.random.intRangeLessThan(u32, 1, 0xffffffff),
.checksum = std.hash.Crc32.hash(name),
};
}

pub fn validate(n: Nonce, name: []const u8) bool {
pub fn validate(n: Fingerprint, name: []const u8) bool {
switch (n.id) {
0x00000000, 0xffffffff => return false,
else => return std.hash.Crc32.hash(name) == n.checksum,
}
}

pub fn int(n: Nonce) u64 {
pub fn int(n: Fingerprint) u64 {
return @bitCast(n);
}
};
Expand Down
8 changes: 4 additions & 4 deletions src/Package/Fetch.zig
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ omit_missing_hash_error: bool,
/// which specifies inclusion rules. This is intended to be true for the first
/// fetch task and false for the recursive dependencies.
allow_missing_paths_field: bool,
allow_missing_nonce: bool,
allow_missing_fingerprint: bool,
allow_name_string: bool,
/// If true and URL points to a Git repository, will use the latest commit.
use_latest_commit: bool,
Expand Down Expand Up @@ -649,7 +649,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {

f.manifest = try Manifest.parse(arena, ast.*, .{
.allow_missing_paths_field = f.allow_missing_paths_field,
.allow_missing_nonce = f.allow_missing_nonce,
.allow_missing_fingerprint = f.allow_missing_fingerprint,
.allow_name_string = f.allow_name_string,
});
const manifest = &f.manifest.?;
Expand Down Expand Up @@ -752,7 +752,7 @@ fn queueJobsForDeps(f: *Fetch) RunError!void {
.job_queue = f.job_queue,
.omit_missing_hash_error = false,
.allow_missing_paths_field = true,
.allow_missing_nonce = true,
.allow_missing_fingerprint = true,
.allow_name_string = true,
.use_latest_commit = false,

Expand Down Expand Up @@ -2323,7 +2323,7 @@ const TestFetchBuilder = struct {
.job_queue = &self.job_queue,
.omit_missing_hash_error = true,
.allow_missing_paths_field = false,
.allow_missing_nonce = true, // so we can keep using the old testdata .tar.gz
.allow_missing_fingerprint = true, // so we can keep using the old testdata .tar.gz
.allow_name_string = true, // so we can keep using the old testdata .tar.gz
.use_latest_commit = true,

Expand Down
26 changes: 13 additions & 13 deletions src/Package/Manifest.zig
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub const ParseOptions = struct {
/// Deprecated, to be removed after 0.14.0 is tagged.
allow_name_string: bool = true,
/// Deprecated, to be removed after 0.14.0 is tagged.
allow_missing_nonce: bool = true,
allow_missing_fingerprint: bool = true,
};

pub const Error = Allocator.Error;
Expand Down Expand Up @@ -81,7 +81,7 @@ pub fn parse(gpa: Allocator, ast: Ast, options: ParseOptions) Error!Manifest {
.paths = .{},
.allow_missing_paths_field = options.allow_missing_paths_field,
.allow_name_string = options.allow_name_string,
.allow_missing_nonce = options.allow_missing_nonce,
.allow_missing_fingerprint = options.allow_missing_fingerprint,
.minimum_zig_version = null,
.buf = .{},
};
Expand Down Expand Up @@ -157,7 +157,7 @@ const Parse = struct {
paths: std.StringArrayHashMapUnmanaged(void),
allow_missing_paths_field: bool,
allow_name_string: bool,
allow_missing_nonce: bool,
allow_missing_fingerprint: bool,
minimum_zig_version: ?std.SemanticVersion,

const InnerError = error{ ParseFailure, OutOfMemory };
Expand All @@ -175,7 +175,7 @@ const Parse = struct {
var have_name = false;
var have_version = false;
var have_included_paths = false;
var nonce: ?Package.Nonce = null;
var fingerprint: ?Package.Fingerprint = null;

for (struct_init.ast.fields) |field_init| {
const name_token = ast.firstToken(field_init) - 2;
Expand All @@ -192,8 +192,8 @@ const Parse = struct {
} else if (mem.eql(u8, field_name, "name")) {
p.name = try parseName(p, field_init);
have_name = true;
} else if (mem.eql(u8, field_name, "nonce")) {
nonce = try parseNonce(p, field_init);
} else if (mem.eql(u8, field_name, "fingerprint")) {
fingerprint = try parseFingerprint(p, field_init);
} else if (mem.eql(u8, field_name, "version")) {
p.version_node = field_init;
const version_text = try parseString(p, field_init);
Expand All @@ -220,16 +220,16 @@ const Parse = struct {
if (!have_name) {
try appendError(p, main_token, "missing top-level 'name' field", .{});
} else {
if (nonce) |n| {
if (fingerprint) |n| {
if (!n.validate(p.name)) {
return fail(p, main_token, "invalid nonce: 0x{x}; if this is a new or forked package, use this value: 0x{x}", .{
n.int(), Package.Nonce.generate(p.name).int(),
return fail(p, main_token, "invalid fingerprint: 0x{x}; if this is a new or forked package, use this value: 0x{x}", .{
n.int(), Package.Fingerprint.generate(p.name).int(),
});
}
p.id = n.id;
} else if (!p.allow_missing_nonce) {
try appendError(p, main_token, "missing top-level 'nonce' field; suggested value: 0x{x}", .{
Package.Nonce.generate(p.name).int(),
} else if (!p.allow_missing_fingerprint) {
try appendError(p, main_token, "missing top-level 'fingerprint' field; suggested value: 0x{x}", .{
Package.Fingerprint.generate(p.name).int(),
});
} else {
p.id = 0;
Expand Down Expand Up @@ -385,7 +385,7 @@ const Parse = struct {
}
}

fn parseNonce(p: *Parse, node: Ast.Node.Index) !Package.Nonce {
fn parseFingerprint(p: *Parse, node: Ast.Node.Index) !Package.Fingerprint {
const ast = p.ast;
const node_tags = ast.nodes.items(.tag);
const main_tokens = ast.nodes.items(.main_token);
Expand Down
20 changes: 10 additions & 10 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4752,10 +4752,10 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
};
var ok_count: usize = 0;

const nonce: Package.Nonce = .generate(sanitized_root_name);
const fingerprint: Package.Fingerprint = .generate(sanitized_root_name);

for (template_paths) |template_path| {
if (templates.write(arena, fs.cwd(), sanitized_root_name, template_path, nonce)) |_| {
if (templates.write(arena, fs.cwd(), sanitized_root_name, template_path, fingerprint)) |_| {
std.log.info("created {s}", .{template_path});
ok_count += 1;
} else |err| switch (err) {
Expand Down Expand Up @@ -5225,7 +5225,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
.job_queue = &job_queue,
.omit_missing_hash_error = true,
.allow_missing_paths_field = false,
.allow_missing_nonce = false,
.allow_missing_fingerprint = false,
.allow_name_string = false,
.use_latest_commit = false,

Expand Down Expand Up @@ -7127,7 +7127,7 @@ fn cmdFetch(
.job_queue = &job_queue,
.omit_missing_hash_error = true,
.allow_missing_paths_field = false,
.allow_missing_nonce = true,
.allow_missing_fingerprint = true,
.allow_name_string = true,
.use_latest_commit = true,

Expand Down Expand Up @@ -7468,10 +7468,10 @@ fn loadManifest(
0,
) catch |err| switch (err) {
error.FileNotFound => {
const nonce: Package.Nonce = .generate(options.root_name);
const fingerprint: Package.Fingerprint = .generate(options.root_name);
var templates = findTemplates(gpa, arena);
defer templates.deinit();
templates.write(arena, options.dir, options.root_name, Package.Manifest.basename, nonce) catch |e| {
templates.write(arena, options.dir, options.root_name, Package.Manifest.basename, fingerprint) catch |e| {
fatal("unable to write {s}: {s}", .{
Package.Manifest.basename, @errorName(e),
});
Expand Down Expand Up @@ -7529,7 +7529,7 @@ const Templates = struct {
out_dir: fs.Dir,
root_name: []const u8,
template_path: []const u8,
nonce: Package.Nonce,
fingerprint: Package.Fingerprint,
) !void {
if (fs.path.dirname(template_path)) |dirname| {
out_dir.makePath(dirname) catch |err| {
Expand All @@ -7555,9 +7555,9 @@ const Templates = struct {
try templates.buffer.appendSlice(root_name);
i += ".NAME".len;
continue;
} else if (std.mem.startsWith(u8, contents[i..], ".NONCE")) {
try templates.buffer.writer().print("0x{x}", .{nonce.int()});
i += ".NONCE".len;
} else if (std.mem.startsWith(u8, contents[i..], ".FINGERPRINT")) {
try templates.buffer.writer().print("0x{x}", .{fingerprint.int()});
i += ".FINGERPRINT".len;
continue;
} else if (std.mem.startsWith(u8, contents[i..], ".ZIGVER")) {
try templates.buffer.appendSlice(build_options.version);
Expand Down

0 comments on commit de43f5e

Please sign in to comment.