+12
package-lock.json
+12
package-lock.json
+35
-8
scripts/setup.js
+35
-8
scripts/setup.js
···
149
149
return result
150
150
}
151
151
152
-
// === CBOR ENCODING (minimal for PLC operations) ===
152
+
// === CBOR ENCODING (dag-cbor compliant for PLC operations) ===
153
+
154
+
function cborEncodeKey(key) {
155
+
// Encode a string key to CBOR bytes (for sorting)
156
+
const bytes = new TextEncoder().encode(key)
157
+
const parts = []
158
+
const mt = 3 << 5 // major type 3 = text string
159
+
if (bytes.length < 24) {
160
+
parts.push(mt | bytes.length)
161
+
} else if (bytes.length < 256) {
162
+
parts.push(mt | 24, bytes.length)
163
+
} else if (bytes.length < 65536) {
164
+
parts.push(mt | 25, bytes.length >> 8, bytes.length & 0xff)
165
+
}
166
+
parts.push(...bytes)
167
+
return new Uint8Array(parts)
168
+
}
169
+
170
+
function compareBytes(a, b) {
171
+
// dag-cbor: bytewise lexicographic order of encoded keys
172
+
const minLen = Math.min(a.length, b.length)
173
+
for (let i = 0; i < minLen; i++) {
174
+
if (a[i] !== b[i]) return a[i] - b[i]
175
+
}
176
+
return a.length - b.length
177
+
}
153
178
154
179
function cborEncode(value) {
155
180
const parts = []
···
172
197
encodeHead(4, val.length)
173
198
for (const item of val) encode(item)
174
199
} else if (typeof val === 'object') {
175
-
const keys = Object.keys(val).sort()
176
-
encodeHead(5, keys.length)
177
-
for (const key of keys) {
200
+
// dag-cbor: sort keys by their CBOR-encoded bytes (length first, then lexicographic)
201
+
const keys = Object.keys(val)
202
+
const keysSorted = keys.sort((a, b) => compareBytes(cborEncodeKey(a), cborEncodeKey(b)))
203
+
encodeHead(5, keysSorted.length)
204
+
for (const key of keysSorted) {
178
205
encode(key)
179
206
encode(val[key])
180
207
}
···
289
316
}
290
317
291
318
async function deriveDidFromOperation(operation) {
292
-
const { sig, ...opWithoutSig } = operation
293
-
const encoded = cborEncode(opWithoutSig)
319
+
// DID is computed from the FULL operation INCLUDING the signature
320
+
const encoded = cborEncode(operation)
294
321
const hash = await sha256(encoded)
295
-
// DID is base32 of first 24 bytes of hash
296
-
return 'did:plc:' + base32Encode(hash.slice(0, 24))
322
+
// DID is base32 of first 15 bytes of hash (= 24 base32 chars)
323
+
return 'did:plc:' + base32Encode(hash.slice(0, 15))
297
324
}
298
325
299
326
function base32Encode(bytes) {