v37-0002-Mix-in-2-bits-of-entropy-into-timestampt-of-UUID.patch
application/octet-stream
Filename: v37-0002-Mix-in-2-bits-of-entropy-into-timestampt-of-UUID.patch
Type: application/octet-stream
Part: 1
Message:
Re: UUID v7
Patch
Format: format-patch
Series: patch v37-0002
Subject: Mix in 2 bits of entropy into timestampt of UUID on MacOS
| File | + | − |
|---|---|---|
| src/backend/utils/adt/uuid.c | 28 | 5 |
From 6f16c43c40bda7cf663c56b3efdb7f58ecd367ea Mon Sep 17 00:00:00 2001
From: Andrey Borodin <amborodin@acm.org>
Date: Sat, 23 Nov 2024 11:15:49 +0300
Subject: [PATCH v37 2/2] Mix in 2 bits of entropy into timestampt of UUID on
MacOS
---
src/backend/utils/adt/uuid.c | 33 ++++++++++++++++++++++++++++-----
1 file changed, 28 insertions(+), 5 deletions(-)
diff --git a/src/backend/utils/adt/uuid.c b/src/backend/utils/adt/uuid.c
index b137805696..ce8cf64908 100644
--- a/src/backend/utils/adt/uuid.c
+++ b/src/backend/utils/adt/uuid.c
@@ -31,12 +31,19 @@
#define NS_PER_US INT64CONST(1000)
/*
- * In UUID version 7, we use 12 bits in "rand_a" to store 1/4096 fractions of
- * sub-millisecond. This is the minimum amount of nanoseconds that guarantees
- * step advancement of sub-millisecond part.
+ * In UUID version 7, we use 12 bits in "rand_a" to store 1/4096
+ * fractions of sub-millisecond. On systems that have only 10 bits of sub-ms
+ * precision we still use 1/4096 parts of a millisecond, but fill lower 2 bits
+ * with random numbers. SUBMS_MINIMAL_STEP is the minimum amount of
+ * nanoseconds that guarantees step of UUID increased clock precision.
*/
+#if defined(__darwin__) || defined(_MSC_VER)
+#define SUBMS_MINIMAL_STEP_BITS 10
+#else
+#define SUBMS_MINIMAL_STEP_BITS 12
+#endif
#define SUBMS_BITS 12
-#define SUBMS_MINIMAL_STEP_NS ((NS_PER_MS / (1 << SUBMS_BITS)) + 1)
+#define SUBMS_MINIMAL_STEP_NS ((NS_PER_MS / (1 << SUBMS_MINIMAL_STEP_BITS)) + 1)
/* sortsupport for uuid */
typedef struct
@@ -523,7 +530,10 @@ generate_uuidv7(int64 ns)
uuid->data[4] = (unsigned char) (unix_ts_ms >> 8);
uuid->data[5] = (unsigned char) unix_ts_ms;
- /* sub-millisecond timestamp fraction (12 bits) */
+ /*
+ * sub-millisecond timestamp fraction (SUBMS_BITS bits, not
+ * SUBMS_MINIMAL_STEP_BITS)
+ */
increased_clock_precision = ((ns % NS_PER_MS) * (1 << SUBMS_BITS)) / NS_PER_MS;
/* Fill the increased clock precision to "rand_a" bits */
@@ -536,6 +546,19 @@ generate_uuidv7(int64 ns)
(errcode(ERRCODE_INTERNAL_ERROR),
errmsg("could not generate random values")));
+#if defined(__darwin__) || defined(WIN32)
+ /*
+ * On MacOS real time is truncted to microseconds. Thus, 2 least
+ * significant are dependent on other time-specific bits, thus they do not
+ * contribute to uniqueness. To make these bit random we mix in two bits
+ * from CSPRNG.
+ *
+ * SUBMS_MINIMAL_STEP is chosen so that we still guarantee monotonicity
+ * despite altering these bits.
+ */
+ uuid->data[7] = uuid->data[7] ^ (uuid->data[8] >> 6);
+#endif
+
/*
* Set magic numbers for a "version 7" (pseudorandom) UUID and variant,
* see https://www.rfc-editor.org/rfc/rfc9562#name-version-field
--
2.39.5 (Apple Git-154)