Specification 0.16 draft: a seal without accuracy, drand's JSON read strictly
The draft v0.16 of datekeys-go at 4f78854 (branch v0.16): SPEC_VERSION
0.16, and testdata, wordlists and annex synced from that commit. The
annex is §79 of the draft, with the CC BY-ND 4.0 license of the
specification in its title and the key of words in 79.7.
A seal without accuracy proves nothing before the opening date (§29.7,
§29.11, as 7e3b810): a valid seal is S4 only when its token carries
accuracy and t plus the accuracy is before round_time; otherwise S5,
with the first reason that holds: late, no accuracy under the BTSP
policy of ETSI EN 319 421 (0.4.0.2023.1.1), or no accuracy. cms.ts reads
hasAccuracy and the policy of the token (tokenIsBTSP); securitycms.ts
gives SealReason, Detail.sealReason and SignerLine.reason; S5 has no
fixed text any more, and verdictLines writes it and the line of a signer
of F6 with the reason, the texts of Go byte for byte (sealReasonText).
encryptFiles returns the verdicts of the area it wrote in
Encrypted.security, as Result.Security of Go, so that a writer warns of
a seal without accuracy (§62.1 rule 19).
drand's JSON is read strictly (§47.1, as b570338): parseDrandJSON, as
ParseDrandJSON of Go, reads RFC 8259 JSON in valid UTF-8 whose value is
an object, with no name repeated in any object, names compared exactly
once their escapes are decoded, a lone escaped surrogate malformed, the
round a number without sign, fraction or exponent from 1 to 2^53 - 1,
and signature and randomness strings, with the error texts of Go.
ParsedRelease is now a Release: no round above 2^53 - 1 is read. The
page reads the answers of the relays with it (drand.ts), as the client
of Go does, and the pasted release with strictJSON and jsonRound
(release-input.ts), so that it never reads another round than step 10.
Tests: security_cms.json with seal_reason (143 cases), the 38 JSON
inputs of release.json, the new cases of signature2_test.go and
drandjson_test.go (with the escapes written as escapes), and the new
fixtures: format3_time_and_key_words opens with the identity that the
words of its words_text give with normalizeWords and wordKey, in the
library and in the page, and format3_full_chunk, whose PAYLOAD_AGE ends
in a full STREAM chunk, opens. check-build.mjs counts words_text among
the secrets of the fixtures.
Reference files made again with Go at 4f78854: mutation-texts.json (its
spec field only), ibe-vectors.json (the two new fixtures, the rest
unchanged) and signing-vectors.json, in an export of 4f78854 with the
same frozen samples read again: the capsules are the same, and the
tokens of the sealer, without accuracy, now give S5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 day ago
|
|
|
// The release object of spec v0.15, §47.1, as provider/release.go,
|
|
|
|
|
// provider/drandjson.go and provider/archive.go of the Go reference: the
|
|
|
|
|
// release of a round as data that is kept: an entry of a release cache or
|
|
|
|
|
// archive and the answer of a release cache or of the Release API; drand's
|
|
|
|
|
// JSON, which a reader accepts too as the input of the caller, read strictly
|
|
|
|
|
// since spec v0.16; the sources of a release in the caller's hand
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
// (provider.Supplier); and a local release archive, the informative format
|
|
|
|
|
// of §50. The texts of the errors are those of the reference.
|
|
|
|
|
//
|
|
|
|
|
// No noble here: the verification of a release is release.ts. This module
|
|
|
|
|
// only decodes, so that the page can read what the person gives before
|
|
|
|
|
// loading the code that opens a capsule.
|
|
|
|
|
|
Specification 0.16 draft: a seal without accuracy, drand's JSON read strictly
The draft v0.16 of datekeys-go at 4f78854 (branch v0.16): SPEC_VERSION
0.16, and testdata, wordlists and annex synced from that commit. The
annex is §79 of the draft, with the CC BY-ND 4.0 license of the
specification in its title and the key of words in 79.7.
A seal without accuracy proves nothing before the opening date (§29.7,
§29.11, as 7e3b810): a valid seal is S4 only when its token carries
accuracy and t plus the accuracy is before round_time; otherwise S5,
with the first reason that holds: late, no accuracy under the BTSP
policy of ETSI EN 319 421 (0.4.0.2023.1.1), or no accuracy. cms.ts reads
hasAccuracy and the policy of the token (tokenIsBTSP); securitycms.ts
gives SealReason, Detail.sealReason and SignerLine.reason; S5 has no
fixed text any more, and verdictLines writes it and the line of a signer
of F6 with the reason, the texts of Go byte for byte (sealReasonText).
encryptFiles returns the verdicts of the area it wrote in
Encrypted.security, as Result.Security of Go, so that a writer warns of
a seal without accuracy (§62.1 rule 19).
drand's JSON is read strictly (§47.1, as b570338): parseDrandJSON, as
ParseDrandJSON of Go, reads RFC 8259 JSON in valid UTF-8 whose value is
an object, with no name repeated in any object, names compared exactly
once their escapes are decoded, a lone escaped surrogate malformed, the
round a number without sign, fraction or exponent from 1 to 2^53 - 1,
and signature and randomness strings, with the error texts of Go.
ParsedRelease is now a Release: no round above 2^53 - 1 is read. The
page reads the answers of the relays with it (drand.ts), as the client
of Go does, and the pasted release with strictJSON and jsonRound
(release-input.ts), so that it never reads another round than step 10.
Tests: security_cms.json with seal_reason (143 cases), the 38 JSON
inputs of release.json, the new cases of signature2_test.go and
drandjson_test.go (with the escapes written as escapes), and the new
fixtures: format3_time_and_key_words opens with the identity that the
words of its words_text give with normalizeWords and wordKey, in the
library and in the page, and format3_full_chunk, whose PAYLOAD_AGE ends
in a full STREAM chunk, opens. check-build.mjs counts words_text among
the secrets of the fixtures.
Reference files made again with Go at 4f78854: mutation-texts.json (its
spec field only), ibe-vectors.json (the two new fixtures, the rest
unchanged) and signing-vectors.json, in an export of 4f78854 with the
same frozen samples read again: the capsules are the same, and the
tokens of the sealer, without accuracy, now give S5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 day ago
|
|
|
import {
|
|
|
|
|
decodeUtf8,
|
|
|
|
|
equalBytes,
|
|
|
|
|
fromHex,
|
|
|
|
|
goQuote,
|
|
|
|
|
sha256,
|
|
|
|
|
toHex,
|
|
|
|
|
utf8Length,
|
|
|
|
|
} from "./bytes.ts";
|
|
|
|
|
import {
|
|
|
|
|
checkSchema,
|
|
|
|
|
Decoder,
|
|
|
|
|
Encoder,
|
|
|
|
|
MAX_SAFE_UINT,
|
|
|
|
|
peek,
|
|
|
|
|
unmarshal,
|
|
|
|
|
} from "./cbor.ts";
|
|
|
|
|
import { DateKeysError, withContext } from "./errors.ts";
|
|
|
|
|
import { QUICKNET_SCHEME, type Profile } from "./profile.ts";
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
|
|
|
|
|
/** The type tag of the release object (key 0). */
|
|
|
|
|
export const RELEASE_TYPE_TAG = "datekeys-release";
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
/** The schema version of the release object (key 1). */
|
|
|
|
|
export const RELEASE_SCHEMA_VERSION = 1;
|
|
|
|
|
/**
|
|
|
|
|
* The largest release object a reader decodes (spec v0.15, §47.1): the
|
|
|
|
|
* object has no frame, and an input of more bytes, or of none, is rejected
|
|
|
|
|
* before it is decoded, with ERR_NON_CANONICAL_CBOR. No valid encoding comes
|
|
|
|
|
* close to it.
|
|
|
|
|
*/
|
|
|
|
|
export const MAX_RELEASE_OBJECT_SIZE = 1024;
|
|
|
|
|
/** The longest signature of the schema: a compressed point of G2 of BLS12-381. */
|
|
|
|
|
export const MAX_SIGNATURE_LEN = 96;
|
|
|
|
|
/** The largest drand JSON read as a release, the bound of a relay response. */
|
|
|
|
|
export const MAX_RELEASE_JSON_SIZE = 8 << 10;
|
|
|
|
|
|
|
|
|
|
/** The type tag of the header of a release archive (spec v0.15, §50). */
|
|
|
|
|
export const ARCHIVE_TYPE_TAG = "datekeys-release-archive";
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
/** The schema version of the header of a release archive. */
|
|
|
|
|
export const ARCHIVE_SCHEMA_VERSION = 1;
|
|
|
|
|
|
|
|
|
|
const RELEASE_KEYS = 5;
|
|
|
|
|
const ARCHIVE_KEYS = 5;
|
|
|
|
|
// Its five keys take at most 1 + 26 + 2 + 35 + 9 + 9 bytes.
|
|
|
|
|
const MAX_ARCHIVE_HEADER = 128;
|
|
|
|
|
// The length of a signature of Quicknet, a compressed point of G1.
|
|
|
|
|
const QUICKNET_SIGNATURE_LEN = 48;
|
|
|
|
|
|
|
|
|
|
/** The material that satisfies a round: for drand, the BLS signature of the round. */
|
|
|
|
|
export interface Release {
|
|
|
|
|
readonly round: number;
|
|
|
|
|
readonly signature: Uint8Array;
|
|
|
|
|
/**
|
|
|
|
|
* The chain the release names, key 2 of a release object (spec v0.15,
|
|
|
|
|
* §47.1), or undefined when it names none, as the answer of a relay and
|
|
|
|
|
* drand's JSON. verifyRelease compares it with the pinned profile.
|
|
|
|
|
*/
|
|
|
|
|
readonly chainHash?: Uint8Array;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
Specification 0.16 draft: a seal without accuracy, drand's JSON read strictly
The draft v0.16 of datekeys-go at 4f78854 (branch v0.16): SPEC_VERSION
0.16, and testdata, wordlists and annex synced from that commit. The
annex is §79 of the draft, with the CC BY-ND 4.0 license of the
specification in its title and the key of words in 79.7.
A seal without accuracy proves nothing before the opening date (§29.7,
§29.11, as 7e3b810): a valid seal is S4 only when its token carries
accuracy and t plus the accuracy is before round_time; otherwise S5,
with the first reason that holds: late, no accuracy under the BTSP
policy of ETSI EN 319 421 (0.4.0.2023.1.1), or no accuracy. cms.ts reads
hasAccuracy and the policy of the token (tokenIsBTSP); securitycms.ts
gives SealReason, Detail.sealReason and SignerLine.reason; S5 has no
fixed text any more, and verdictLines writes it and the line of a signer
of F6 with the reason, the texts of Go byte for byte (sealReasonText).
encryptFiles returns the verdicts of the area it wrote in
Encrypted.security, as Result.Security of Go, so that a writer warns of
a seal without accuracy (§62.1 rule 19).
drand's JSON is read strictly (§47.1, as b570338): parseDrandJSON, as
ParseDrandJSON of Go, reads RFC 8259 JSON in valid UTF-8 whose value is
an object, with no name repeated in any object, names compared exactly
once their escapes are decoded, a lone escaped surrogate malformed, the
round a number without sign, fraction or exponent from 1 to 2^53 - 1,
and signature and randomness strings, with the error texts of Go.
ParsedRelease is now a Release: no round above 2^53 - 1 is read. The
page reads the answers of the relays with it (drand.ts), as the client
of Go does, and the pasted release with strictJSON and jsonRound
(release-input.ts), so that it never reads another round than step 10.
Tests: security_cms.json with seal_reason (143 cases), the 38 JSON
inputs of release.json, the new cases of signature2_test.go and
drandjson_test.go (with the escapes written as escapes), and the new
fixtures: format3_time_and_key_words opens with the identity that the
words of its words_text give with normalizeWords and wordKey, in the
library and in the page, and format3_full_chunk, whose PAYLOAD_AGE ends
in a full STREAM chunk, opens. check-build.mjs counts words_text among
the secrets of the fixtures.
Reference files made again with Go at 4f78854: mutation-texts.json (its
spec field only), ibe-vectors.json (the two new fixtures, the rest
unchanged) and signing-vectors.json, in an export of 4f78854 with the
same frozen samples read again: the capsules are the same, and the
tokens of the sealer, without accuracy, now give S5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 day ago
|
|
|
* A release as the caller gives it, before step 10. Since spec v0.16 the
|
|
|
|
|
* round of drand's JSON is at most 2^53 - 1, as that of a release object
|
|
|
|
|
* (§47.1), so it is a Release.
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
*/
|
Specification 0.16 draft: a seal without accuracy, drand's JSON read strictly
The draft v0.16 of datekeys-go at 4f78854 (branch v0.16): SPEC_VERSION
0.16, and testdata, wordlists and annex synced from that commit. The
annex is §79 of the draft, with the CC BY-ND 4.0 license of the
specification in its title and the key of words in 79.7.
A seal without accuracy proves nothing before the opening date (§29.7,
§29.11, as 7e3b810): a valid seal is S4 only when its token carries
accuracy and t plus the accuracy is before round_time; otherwise S5,
with the first reason that holds: late, no accuracy under the BTSP
policy of ETSI EN 319 421 (0.4.0.2023.1.1), or no accuracy. cms.ts reads
hasAccuracy and the policy of the token (tokenIsBTSP); securitycms.ts
gives SealReason, Detail.sealReason and SignerLine.reason; S5 has no
fixed text any more, and verdictLines writes it and the line of a signer
of F6 with the reason, the texts of Go byte for byte (sealReasonText).
encryptFiles returns the verdicts of the area it wrote in
Encrypted.security, as Result.Security of Go, so that a writer warns of
a seal without accuracy (§62.1 rule 19).
drand's JSON is read strictly (§47.1, as b570338): parseDrandJSON, as
ParseDrandJSON of Go, reads RFC 8259 JSON in valid UTF-8 whose value is
an object, with no name repeated in any object, names compared exactly
once their escapes are decoded, a lone escaped surrogate malformed, the
round a number without sign, fraction or exponent from 1 to 2^53 - 1,
and signature and randomness strings, with the error texts of Go.
ParsedRelease is now a Release: no round above 2^53 - 1 is read. The
page reads the answers of the relays with it (drand.ts), as the client
of Go does, and the pasted release with strictJSON and jsonRound
(release-input.ts), so that it never reads another round than step 10.
Tests: security_cms.json with seal_reason (143 cases), the 38 JSON
inputs of release.json, the new cases of signature2_test.go and
drandjson_test.go (with the escapes written as escapes), and the new
fixtures: format3_time_and_key_words opens with the identity that the
words of its words_text give with normalizeWords and wordKey, in the
library and in the page, and format3_full_chunk, whose PAYLOAD_AGE ends
in a full STREAM chunk, opens. check-build.mjs counts words_text among
the secrets of the fixtures.
Reference files made again with Go at 4f78854: mutation-texts.json (its
spec field only), ibe-vectors.json (the two new fixtures, the rest
unchanged) and signing-vectors.json, in an export of 4f78854 with the
same frozen samples read again: the capsules are the same, and the
tokens of the sealer, without accuracy, now give S5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 day ago
|
|
|
export type ParsedRelease = Release;
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// The release object
|
|
|
|
|
|
|
|
|
|
interface ReleaseWire {
|
|
|
|
|
chainHash: Uint8Array;
|
|
|
|
|
round: number;
|
|
|
|
|
signature: Uint8Array;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function encodeWire(e: Encoder, w: ReleaseWire): void {
|
|
|
|
|
e.map(RELEASE_KEYS);
|
|
|
|
|
e.uint(0);
|
|
|
|
|
e.text(RELEASE_TYPE_TAG);
|
|
|
|
|
e.uint(1);
|
|
|
|
|
e.uint(RELEASE_SCHEMA_VERSION);
|
|
|
|
|
e.uint(2);
|
|
|
|
|
e.bstr(w.chainHash);
|
|
|
|
|
e.uint(3);
|
|
|
|
|
e.uint(w.round);
|
|
|
|
|
e.uint(4);
|
|
|
|
|
e.bstr(w.signature);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reads the map with every CDDL rule of the release object, all of them
|
|
|
|
|
// ERR_NON_CANONICAL_CBOR: what each field means against the pinned profile
|
|
|
|
|
// and the DateKey is checked by verifyRelease, at step 10.
|
|
|
|
|
function decodeWire(d: Decoder): ReleaseWire {
|
|
|
|
|
const w: ReleaseWire = {
|
|
|
|
|
chainHash: new Uint8Array(0),
|
|
|
|
|
round: 0,
|
|
|
|
|
signature: new Uint8Array(0),
|
|
|
|
|
};
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
const pairs = d.map(RELEASE_KEYS);
|
|
|
|
|
if (pairs !== RELEASE_KEYS)
|
|
|
|
|
throw new DateKeysError(
|
|
|
|
|
"ERR_NON_CANONICAL_CBOR",
|
|
|
|
|
`${pairs} keys, want all ${RELEASE_KEYS}`,
|
|
|
|
|
);
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
for (let want = 0; want < RELEASE_KEYS; want++) {
|
|
|
|
|
const k = d.key();
|
|
|
|
|
if (k !== want)
|
|
|
|
|
throw new DateKeysError(
|
|
|
|
|
"ERR_NON_CANONICAL_CBOR",
|
|
|
|
|
`key ${k} where key ${want} was expected`,
|
|
|
|
|
);
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
withContext(`key ${k}`, () => {
|
|
|
|
|
switch (want) {
|
|
|
|
|
case 0:
|
|
|
|
|
d.text(utf8Length(RELEASE_TYPE_TAG));
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
d.uint(RELEASE_SCHEMA_VERSION);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
w.chainHash = d.bstr(32, 32);
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
w.round = d.uint(MAX_SAFE_UINT);
|
|
|
|
|
if (w.round === 0)
|
|
|
|
|
throw new DateKeysError("ERR_NON_CANONICAL_CBOR", "round 0");
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
w.signature = d.bstr(1, MAX_SIGNATURE_LEN);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
d.endMap();
|
|
|
|
|
return w;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The release object of `r`, as a release cache or archive keeps it (spec v0.15,
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
* §47.1): its chain hash, its round and its signature, as
|
|
|
|
|
* provider.EncodeRelease. It does not verify the release: verifyRelease
|
|
|
|
|
* does, against the pinned profile.
|
|
|
|
|
*/
|
|
|
|
|
export function encodeRelease(r: Release): Uint8Array {
|
|
|
|
|
const chainHash = r.chainHash ?? new Uint8Array(0);
|
|
|
|
|
if (chainHash.length !== 32) {
|
|
|
|
|
throw new DateKeysError(
|
|
|
|
|
"ERR_NON_CANONICAL_CBOR",
|
|
|
|
|
`provider: release object: chain hash of ${chainHash.length} bytes, want 32`,
|
|
|
|
|
);
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
}
|
|
|
|
|
if (!Number.isSafeInteger(r.round) || r.round < 1) {
|
|
|
|
|
throw new DateKeysError(
|
|
|
|
|
"ERR_NON_CANONICAL_CBOR",
|
|
|
|
|
`provider: release object: round ${r.round} outside 1..${MAX_SAFE_UINT}`,
|
|
|
|
|
);
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
}
|
|
|
|
|
if (r.signature.length === 0 || r.signature.length > MAX_SIGNATURE_LEN) {
|
|
|
|
|
throw new DateKeysError(
|
|
|
|
|
"ERR_NON_CANONICAL_CBOR",
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
`provider: release object: signature of ${r.signature.length} bytes outside 1..${MAX_SIGNATURE_LEN}`,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
const e = new Encoder();
|
|
|
|
|
encodeWire(e, { chainHash, round: r.round, signature: r.signature });
|
|
|
|
|
return e.out();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Decodes a release object (spec v0.15, §47.1) with the layers of spec §69.1
|
|
|
|
|
* that it has, as provider.DecodeRelease: its size, 1 to
|
|
|
|
|
* MAX_RELEASE_OBJECT_SIZE bytes; its type and schema version
|
|
|
|
|
* (ERR_NON_CANONICAL_CBOR, then ERR_UNSUPPORTED_VERSION); its encoding and
|
|
|
|
|
* schema (ERR_NON_CANONICAL_CBOR). The release names its chain, which
|
|
|
|
|
* verifyRelease checks against the pinned profile at step 10 of spec §63.
|
|
|
|
|
*/
|
|
|
|
|
export function decodeRelease(b: Uint8Array): Release {
|
|
|
|
|
if (b.length === 0 || b.length > MAX_RELEASE_OBJECT_SIZE) {
|
|
|
|
|
throw new DateKeysError(
|
|
|
|
|
"ERR_NON_CANONICAL_CBOR",
|
|
|
|
|
`provider: release object of ${b.length} bytes, outside 1..${MAX_RELEASE_OBJECT_SIZE}`,
|
|
|
|
|
);
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
}
|
|
|
|
|
const w = withContext("provider: release object", () => {
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
checkSchema(b, RELEASE_TYPE_TAG, RELEASE_SCHEMA_VERSION);
|
|
|
|
|
return unmarshal(b, decodeWire, encodeWire);
|
|
|
|
|
});
|
|
|
|
|
return { round: w.round, signature: w.signature, chainHash: w.chainHash };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Reports whether `b` is read as drand's JSON rather than as a release
|
|
|
|
|
* object: its first byte other than a JSON space is "{" (spec v0.15, §47.1).
|
|
|
|
|
*/
|
|
|
|
|
export function isDrandJSON(b: Uint8Array): boolean {
|
|
|
|
|
for (const c of b) {
|
|
|
|
|
if (c === 0x20 || c === 0x09 || c === 0x0a || c === 0x0d) continue;
|
|
|
|
|
return c === 0x7b;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Reads a release that the caller supplies, as provider.ParseRelease:
|
Specification 0.16 draft: a seal without accuracy, drand's JSON read strictly
The draft v0.16 of datekeys-go at 4f78854 (branch v0.16): SPEC_VERSION
0.16, and testdata, wordlists and annex synced from that commit. The
annex is §79 of the draft, with the CC BY-ND 4.0 license of the
specification in its title and the key of words in 79.7.
A seal without accuracy proves nothing before the opening date (§29.7,
§29.11, as 7e3b810): a valid seal is S4 only when its token carries
accuracy and t plus the accuracy is before round_time; otherwise S5,
with the first reason that holds: late, no accuracy under the BTSP
policy of ETSI EN 319 421 (0.4.0.2023.1.1), or no accuracy. cms.ts reads
hasAccuracy and the policy of the token (tokenIsBTSP); securitycms.ts
gives SealReason, Detail.sealReason and SignerLine.reason; S5 has no
fixed text any more, and verdictLines writes it and the line of a signer
of F6 with the reason, the texts of Go byte for byte (sealReasonText).
encryptFiles returns the verdicts of the area it wrote in
Encrypted.security, as Result.Security of Go, so that a writer warns of
a seal without accuracy (§62.1 rule 19).
drand's JSON is read strictly (§47.1, as b570338): parseDrandJSON, as
ParseDrandJSON of Go, reads RFC 8259 JSON in valid UTF-8 whose value is
an object, with no name repeated in any object, names compared exactly
once their escapes are decoded, a lone escaped surrogate malformed, the
round a number without sign, fraction or exponent from 1 to 2^53 - 1,
and signature and randomness strings, with the error texts of Go.
ParsedRelease is now a Release: no round above 2^53 - 1 is read. The
page reads the answers of the relays with it (drand.ts), as the client
of Go does, and the pasted release with strictJSON and jsonRound
(release-input.ts), so that it never reads another round than step 10.
Tests: security_cms.json with seal_reason (143 cases), the 38 JSON
inputs of release.json, the new cases of signature2_test.go and
drandjson_test.go (with the escapes written as escapes), and the new
fixtures: format3_time_and_key_words opens with the identity that the
words of its words_text give with normalizeWords and wordKey, in the
library and in the page, and format3_full_chunk, whose PAYLOAD_AGE ends
in a full STREAM chunk, opens. check-build.mjs counts words_text among
the secrets of the fixtures.
Reference files made again with Go at 4f78854: mutation-texts.json (its
spec field only), ibe-vectors.json (the two new fixtures, the rest
unchanged) and signing-vectors.json, in an export of 4f78854 with the
same frozen samples read again: the capsules are the same, and the
tokens of the sealer, without accuracy, now give S5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 day ago
|
|
|
* drand's JSON when isDrandJSON, read strictly by parseDrandJSON, or else a
|
|
|
|
|
* release object, with decodeRelease. drand's JSON is the answer of a relay,
|
|
|
|
|
* {"round": …, "signature": "…"}, with an optional "randomness" that must be
|
|
|
|
|
* SHA-256 of the signature; it does not name its chain, so the release has no
|
|
|
|
|
* chain hash, and any failure to read it is ERR_RELEASE_INVALID. It is
|
|
|
|
|
* accepted as input, never written.
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
*/
|
|
|
|
|
export async function parseRelease(b: Uint8Array): Promise<ParsedRelease> {
|
|
|
|
|
return isDrandJSON(b) ? parseDrandJSON(b) : decodeRelease(b);
|
|
|
|
|
}
|
|
|
|
|
|
Specification 0.16 draft: a seal without accuracy, drand's JSON read strictly
The draft v0.16 of datekeys-go at 4f78854 (branch v0.16): SPEC_VERSION
0.16, and testdata, wordlists and annex synced from that commit. The
annex is §79 of the draft, with the CC BY-ND 4.0 license of the
specification in its title and the key of words in 79.7.
A seal without accuracy proves nothing before the opening date (§29.7,
§29.11, as 7e3b810): a valid seal is S4 only when its token carries
accuracy and t plus the accuracy is before round_time; otherwise S5,
with the first reason that holds: late, no accuracy under the BTSP
policy of ETSI EN 319 421 (0.4.0.2023.1.1), or no accuracy. cms.ts reads
hasAccuracy and the policy of the token (tokenIsBTSP); securitycms.ts
gives SealReason, Detail.sealReason and SignerLine.reason; S5 has no
fixed text any more, and verdictLines writes it and the line of a signer
of F6 with the reason, the texts of Go byte for byte (sealReasonText).
encryptFiles returns the verdicts of the area it wrote in
Encrypted.security, as Result.Security of Go, so that a writer warns of
a seal without accuracy (§62.1 rule 19).
drand's JSON is read strictly (§47.1, as b570338): parseDrandJSON, as
ParseDrandJSON of Go, reads RFC 8259 JSON in valid UTF-8 whose value is
an object, with no name repeated in any object, names compared exactly
once their escapes are decoded, a lone escaped surrogate malformed, the
round a number without sign, fraction or exponent from 1 to 2^53 - 1,
and signature and randomness strings, with the error texts of Go.
ParsedRelease is now a Release: no round above 2^53 - 1 is read. The
page reads the answers of the relays with it (drand.ts), as the client
of Go does, and the pasted release with strictJSON and jsonRound
(release-input.ts), so that it never reads another round than step 10.
Tests: security_cms.json with seal_reason (143 cases), the 38 JSON
inputs of release.json, the new cases of signature2_test.go and
drandjson_test.go (with the escapes written as escapes), and the new
fixtures: format3_time_and_key_words opens with the identity that the
words of its words_text give with normalizeWords and wordKey, in the
library and in the page, and format3_full_chunk, whose PAYLOAD_AGE ends
in a full STREAM chunk, opens. check-build.mjs counts words_text among
the secrets of the fixtures.
Reference files made again with Go at 4f78854: mutation-texts.json (its
spec field only), ibe-vectors.json (the two new fixtures, the rest
unchanged) and signing-vectors.json, in an export of 4f78854 with the
same frozen samples read again: the capsules are the same, and the
tokens of the sealer, without accuracy, now give S5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 day ago
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// drand's JSON, read strictly
|
|
|
|
|
//
|
|
|
|
|
// The strict reading of drand's JSON (spec v0.16, §47.1), as
|
|
|
|
|
// provider/drandjson.go of the reference: JSON of RFC 8259, in UTF-8, whose
|
|
|
|
|
// value is an object; no object of the JSON repeats a name, and names are
|
|
|
|
|
// compared exactly, code point by code point, once their escapes are
|
|
|
|
|
// decoded, so that "\u0072ound" is round and Round is another name; and an
|
Specification 0.16 draft: a seal without accuracy, drand's JSON read strictly
The draft v0.16 of datekeys-go at 4f78854 (branch v0.16): SPEC_VERSION
0.16, and testdata, wordlists and annex synced from that commit. The
annex is §79 of the draft, with the CC BY-ND 4.0 license of the
specification in its title and the key of words in 79.7.
A seal without accuracy proves nothing before the opening date (§29.7,
§29.11, as 7e3b810): a valid seal is S4 only when its token carries
accuracy and t plus the accuracy is before round_time; otherwise S5,
with the first reason that holds: late, no accuracy under the BTSP
policy of ETSI EN 319 421 (0.4.0.2023.1.1), or no accuracy. cms.ts reads
hasAccuracy and the policy of the token (tokenIsBTSP); securitycms.ts
gives SealReason, Detail.sealReason and SignerLine.reason; S5 has no
fixed text any more, and verdictLines writes it and the line of a signer
of F6 with the reason, the texts of Go byte for byte (sealReasonText).
encryptFiles returns the verdicts of the area it wrote in
Encrypted.security, as Result.Security of Go, so that a writer warns of
a seal without accuracy (§62.1 rule 19).
drand's JSON is read strictly (§47.1, as b570338): parseDrandJSON, as
ParseDrandJSON of Go, reads RFC 8259 JSON in valid UTF-8 whose value is
an object, with no name repeated in any object, names compared exactly
once their escapes are decoded, a lone escaped surrogate malformed, the
round a number without sign, fraction or exponent from 1 to 2^53 - 1,
and signature and randomness strings, with the error texts of Go.
ParsedRelease is now a Release: no round above 2^53 - 1 is read. The
page reads the answers of the relays with it (drand.ts), as the client
of Go does, and the pasted release with strictJSON and jsonRound
(release-input.ts), so that it never reads another round than step 10.
Tests: security_cms.json with seal_reason (143 cases), the 38 JSON
inputs of release.json, the new cases of signature2_test.go and
drandjson_test.go (with the escapes written as escapes), and the new
fixtures: format3_time_and_key_words opens with the identity that the
words of its words_text give with normalizeWords and wordKey, in the
library and in the page, and format3_full_chunk, whose PAYLOAD_AGE ends
in a full STREAM chunk, opens. check-build.mjs counts words_text among
the secrets of the fixtures.
Reference files made again with Go at 4f78854: mutation-texts.json (its
spec field only), ibe-vectors.json (the two new fixtures, the rest
unchanged) and signing-vectors.json, in an export of 4f78854 with the
same frozen samples read again: the capsules are the same, and the
tokens of the sealer, without accuracy, now give S5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 day ago
|
|
|
// escape of a surrogate that does not pair with the next one makes the JSON
|
|
|
|
|
// malformed. A common JSON reader keeps the last of two repeated names, or
|
|
|
|
|
// does not tell upper from lower case in them, and two readers would see two
|
|
|
|
|
// rounds in the same input.
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A member of the outer object of drand's JSON: its name, decoded; the kind
|
|
|
|
|
* of its value, its first character ('"', '{', '[', 't', 'f' or 'n'), or '0'
|
|
|
|
|
* for a number; the text of the value as written; and for a string, the
|
|
|
|
|
* string decoded.
|
|
|
|
|
*/
|
|
|
|
|
export interface JSONMember {
|
|
|
|
|
readonly name: string;
|
|
|
|
|
readonly kind: string;
|
|
|
|
|
readonly raw: string;
|
|
|
|
|
readonly str: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Reads `b` as a JSON object with the strict rules of spec v0.16, §47.1, and
|
|
|
|
|
* returns the members of the outer object in their order, or undefined when
|
|
|
|
|
* `b` breaks one: it is not UTF-8, its value is not an object, an object
|
|
|
|
|
* repeats a name, or a string escapes a surrogate without its pair.
|
|
|
|
|
*/
|
|
|
|
|
export function strictJSON(b: Uint8Array): JSONMember[] | undefined {
|
|
|
|
|
const text = decodeUtf8(b);
|
|
|
|
|
if (text === undefined) return undefined;
|
|
|
|
|
const r = new JSONReader(text);
|
|
|
|
|
r.space();
|
|
|
|
|
if (!r.at("{")) return undefined;
|
|
|
|
|
const members = r.object(true);
|
|
|
|
|
r.space();
|
|
|
|
|
return members !== undefined && r.i === text.length ? members : undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reads JSON from the text s at i. The text is decoded UTF-8, so it holds no
|
|
|
|
|
// lone surrogate, and a byte order mark at its start stays, as a character
|
|
|
|
|
// that is not a space of JSON.
|
|
|
|
|
class JSONReader {
|
|
|
|
|
i = 0;
|
|
|
|
|
private readonly s: string;
|
|
|
|
|
|
|
|
|
|
constructor(s: string) {
|
|
|
|
|
this.s = s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
at(c: string): boolean {
|
|
|
|
|
return this.s[this.i] === c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Skips the four spaces of JSON.
|
|
|
|
|
space(): void {
|
|
|
|
|
while (this.i < this.s.length && " \t\n\r".includes(this.s[this.i]!))
|
|
|
|
|
this.i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// One value of any kind, undefined when it breaks the grammar.
|
|
|
|
|
value(): Omit<JSONMember, "name"> | undefined {
|
|
|
|
|
const start = this.i;
|
|
|
|
|
const c = this.s[this.i];
|
|
|
|
|
let kind = c;
|
|
|
|
|
let str = "";
|
|
|
|
|
let ok = false;
|
|
|
|
|
if (c === "{") ok = this.object(false) !== undefined;
|
|
|
|
|
else if (c === "[") ok = this.array();
|
|
|
|
|
else if (c === '"') {
|
|
|
|
|
const v = this.string();
|
|
|
|
|
ok = v !== undefined;
|
|
|
|
|
str = v ?? "";
|
|
|
|
|
} else if (c === "t") ok = this.literal("true");
|
|
|
|
|
else if (c === "f") ok = this.literal("false");
|
|
|
|
|
else if (c === "n") ok = this.literal("null");
|
|
|
|
|
else if (c === "-" || (c !== undefined && c >= "0" && c <= "9")) {
|
|
|
|
|
kind = "0";
|
|
|
|
|
ok = this.number();
|
|
|
|
|
}
|
|
|
|
|
return ok
|
|
|
|
|
? { kind: kind!, raw: this.s.slice(start, this.i), str }
|
|
|
|
|
: undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// An object, with no name twice; its members when keep is set.
|
|
|
|
|
object(keep: boolean): JSONMember[] | undefined {
|
|
|
|
|
this.i++; // {
|
|
|
|
|
this.space();
|
|
|
|
|
const out: JSONMember[] = [];
|
|
|
|
|
if (this.at("}")) {
|
|
|
|
|
this.i++;
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
const seen = new Set<string>();
|
|
|
|
|
for (;;) {
|
|
|
|
|
this.space();
|
|
|
|
|
if (!this.at('"')) return undefined;
|
|
|
|
|
const name = this.string();
|
|
|
|
|
if (name === undefined || seen.has(name)) return undefined;
|
|
|
|
|
seen.add(name);
|
|
|
|
|
this.space();
|
|
|
|
|
if (!this.at(":")) return undefined;
|
|
|
|
|
this.i++;
|
|
|
|
|
this.space();
|
|
|
|
|
const m = this.value();
|
|
|
|
|
if (m === undefined) return undefined;
|
|
|
|
|
if (keep) out.push({ name, ...m });
|
|
|
|
|
this.space();
|
|
|
|
|
if (this.at(",")) this.i++;
|
|
|
|
|
else if (this.at("}")) {
|
|
|
|
|
this.i++;
|
|
|
|
|
return out;
|
|
|
|
|
} else return undefined;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
array(): boolean {
|
|
|
|
|
this.i++; // [
|
|
|
|
|
this.space();
|
|
|
|
|
if (this.at("]")) {
|
|
|
|
|
this.i++;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
for (;;) {
|
|
|
|
|
this.space();
|
|
|
|
|
if (this.value() === undefined) return false;
|
|
|
|
|
this.space();
|
|
|
|
|
if (this.at(",")) this.i++;
|
|
|
|
|
else if (this.at("]")) {
|
|
|
|
|
this.i++;
|
|
|
|
|
return true;
|
|
|
|
|
} else return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A string, with its escapes decoded; a surrogate escaped alone, without
|
|
|
|
|
// its pair, breaks it.
|
|
|
|
|
string(): string | undefined {
|
|
|
|
|
this.i++; // "
|
|
|
|
|
let out = "";
|
|
|
|
|
while (this.i < this.s.length) {
|
|
|
|
|
const c = this.s[this.i]!;
|
|
|
|
|
if (c === '"') {
|
|
|
|
|
this.i++;
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
if (c < " ") return undefined;
|
|
|
|
|
if (c !== "\\") {
|
|
|
|
|
out += c;
|
|
|
|
|
this.i++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
const e = this.s[this.i + 1];
|
|
|
|
|
this.i += 2;
|
|
|
|
|
const k = e === undefined ? -1 : '"\\/bfnrt'.indexOf(e);
|
|
|
|
|
if (k >= 0) {
|
|
|
|
|
out += '"\\/\b\f\n\r\t'[k];
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (e !== "u") return undefined;
|
|
|
|
|
let u = this.hex4();
|
|
|
|
|
if (u === undefined || (u >= 0xdc00 && u <= 0xdfff)) return undefined;
|
|
|
|
|
if (u >= 0xd800 && u <= 0xdbff) {
|
|
|
|
|
if (!this.s.startsWith("\\u", this.i)) return undefined;
|
|
|
|
|
this.i += 2;
|
|
|
|
|
const low = this.hex4();
|
|
|
|
|
if (low === undefined || low < 0xdc00 || low > 0xdfff)
|
|
|
|
|
return undefined;
|
|
|
|
|
u = 0x10000 + ((u - 0xd800) << 10) + (low - 0xdc00);
|
|
|
|
|
}
|
|
|
|
|
out += String.fromCodePoint(u);
|
|
|
|
|
}
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The four hexadecimal digits of an escape \u.
|
|
|
|
|
hex4(): number | undefined {
|
|
|
|
|
const h = this.s.slice(this.i, this.i + 4);
|
|
|
|
|
if (!/^[0-9a-fA-F]{4}$/.test(h)) return undefined;
|
|
|
|
|
this.i += 4;
|
|
|
|
|
return parseInt(h, 16);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
literal(word: string): boolean {
|
|
|
|
|
if (!this.s.startsWith(word, this.i)) return false;
|
|
|
|
|
this.i += word.length;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A number of the grammar of RFC 8259: a minus, an integer part without
|
|
|
|
|
// leading zeros, and an optional fraction and exponent.
|
|
|
|
|
number(): boolean {
|
|
|
|
|
const digits = (): number => {
|
|
|
|
|
const from = this.i;
|
|
|
|
|
while (this.i < this.s.length && /[0-9]/.test(this.s[this.i]!))
|
|
|
|
|
this.i++;
|
|
|
|
|
return this.i - from;
|
|
|
|
|
};
|
|
|
|
|
if (this.at("-")) this.i++;
|
|
|
|
|
if (this.at("0")) this.i++;
|
|
|
|
|
else if (digits() === 0) return false;
|
|
|
|
|
if (this.at(".")) {
|
|
|
|
|
this.i++;
|
|
|
|
|
if (digits() === 0) return false;
|
|
|
|
|
}
|
|
|
|
|
if (this.at("e") || this.at("E")) {
|
|
|
|
|
this.i++;
|
|
|
|
|
if (this.at("+") || this.at("-")) this.i++;
|
|
|
|
|
if (digits() === 0) return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The round of drand's JSON (spec v0.16, §47.1): a number without sign,
|
|
|
|
|
* fraction or exponent, from 1 to 2^53 - 1, as in the release object;
|
|
|
|
|
* undefined for any other member.
|
|
|
|
|
*/
|
|
|
|
|
export function jsonRound(m: JSONMember): number | undefined {
|
|
|
|
|
if (m.kind !== "0" || !/^[1-9][0-9]{0,15}$/.test(m.raw)) return undefined;
|
|
|
|
|
const n = Number(m.raw);
|
|
|
|
|
return n <= MAX_SAFE_UINT ? n : undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Reads the JSON of a drand relay with the strict rules of spec v0.16, §47.1,
|
|
|
|
|
* as provider.ParseDrandJSON: at most MAX_RELEASE_JSON_SIZE bytes of JSON
|
|
|
|
|
* whose value is an object, with no repeated name and names compared exactly
|
|
|
|
|
* once their escapes are decoded; "round" a number without sign, fraction or
|
|
|
|
|
* exponent, from 1 to 2^53 - 1; "signature" a string of hexadecimal, in lower
|
|
|
|
|
* or upper case; and "randomness", when present, a string with SHA-256 of the
|
|
|
|
|
* signature in hexadecimal. Other members are ignored. Any failure is
|
|
|
|
|
* ERR_RELEASE_INVALID, with the texts of the reference. The release names no
|
|
|
|
|
* chain. The page reads the answers of the relays of drand with it too.
|
|
|
|
|
*/
|
|
|
|
|
export async function parseDrandJSON(b: Uint8Array): Promise<Release> {
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
if (b.length > MAX_RELEASE_JSON_SIZE) {
|
|
|
|
|
throw new DateKeysError(
|
|
|
|
|
"ERR_RELEASE_INVALID",
|
|
|
|
|
`provider: drand JSON of ${b.length} bytes, larger than ${MAX_RELEASE_JSON_SIZE}`,
|
|
|
|
|
);
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
}
|
|
|
|
|
const malformed = (): DateKeysError =>
|
|
|
|
|
new DateKeysError(
|
|
|
|
|
"ERR_RELEASE_INVALID",
|
|
|
|
|
"provider: drand JSON: malformed, or without round or signature",
|
|
|
|
|
);
|
Specification 0.16 draft: a seal without accuracy, drand's JSON read strictly
The draft v0.16 of datekeys-go at 4f78854 (branch v0.16): SPEC_VERSION
0.16, and testdata, wordlists and annex synced from that commit. The
annex is §79 of the draft, with the CC BY-ND 4.0 license of the
specification in its title and the key of words in 79.7.
A seal without accuracy proves nothing before the opening date (§29.7,
§29.11, as 7e3b810): a valid seal is S4 only when its token carries
accuracy and t plus the accuracy is before round_time; otherwise S5,
with the first reason that holds: late, no accuracy under the BTSP
policy of ETSI EN 319 421 (0.4.0.2023.1.1), or no accuracy. cms.ts reads
hasAccuracy and the policy of the token (tokenIsBTSP); securitycms.ts
gives SealReason, Detail.sealReason and SignerLine.reason; S5 has no
fixed text any more, and verdictLines writes it and the line of a signer
of F6 with the reason, the texts of Go byte for byte (sealReasonText).
encryptFiles returns the verdicts of the area it wrote in
Encrypted.security, as Result.Security of Go, so that a writer warns of
a seal without accuracy (§62.1 rule 19).
drand's JSON is read strictly (§47.1, as b570338): parseDrandJSON, as
ParseDrandJSON of Go, reads RFC 8259 JSON in valid UTF-8 whose value is
an object, with no name repeated in any object, names compared exactly
once their escapes are decoded, a lone escaped surrogate malformed, the
round a number without sign, fraction or exponent from 1 to 2^53 - 1,
and signature and randomness strings, with the error texts of Go.
ParsedRelease is now a Release: no round above 2^53 - 1 is read. The
page reads the answers of the relays with it (drand.ts), as the client
of Go does, and the pasted release with strictJSON and jsonRound
(release-input.ts), so that it never reads another round than step 10.
Tests: security_cms.json with seal_reason (143 cases), the 38 JSON
inputs of release.json, the new cases of signature2_test.go and
drandjson_test.go (with the escapes written as escapes), and the new
fixtures: format3_time_and_key_words opens with the identity that the
words of its words_text give with normalizeWords and wordKey, in the
library and in the page, and format3_full_chunk, whose PAYLOAD_AGE ends
in a full STREAM chunk, opens. check-build.mjs counts words_text among
the secrets of the fixtures.
Reference files made again with Go at 4f78854: mutation-texts.json (its
spec field only), ibe-vectors.json (the two new fixtures, the rest
unchanged) and signing-vectors.json, in an export of 4f78854 with the
same frozen samples read again: the capsules are the same, and the
tokens of the sealer, without accuracy, now give S5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 day ago
|
|
|
const members = strictJSON(b);
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
if (members === undefined) throw malformed();
|
Specification 0.16 draft: a seal without accuracy, drand's JSON read strictly
The draft v0.16 of datekeys-go at 4f78854 (branch v0.16): SPEC_VERSION
0.16, and testdata, wordlists and annex synced from that commit. The
annex is §79 of the draft, with the CC BY-ND 4.0 license of the
specification in its title and the key of words in 79.7.
A seal without accuracy proves nothing before the opening date (§29.7,
§29.11, as 7e3b810): a valid seal is S4 only when its token carries
accuracy and t plus the accuracy is before round_time; otherwise S5,
with the first reason that holds: late, no accuracy under the BTSP
policy of ETSI EN 319 421 (0.4.0.2023.1.1), or no accuracy. cms.ts reads
hasAccuracy and the policy of the token (tokenIsBTSP); securitycms.ts
gives SealReason, Detail.sealReason and SignerLine.reason; S5 has no
fixed text any more, and verdictLines writes it and the line of a signer
of F6 with the reason, the texts of Go byte for byte (sealReasonText).
encryptFiles returns the verdicts of the area it wrote in
Encrypted.security, as Result.Security of Go, so that a writer warns of
a seal without accuracy (§62.1 rule 19).
drand's JSON is read strictly (§47.1, as b570338): parseDrandJSON, as
ParseDrandJSON of Go, reads RFC 8259 JSON in valid UTF-8 whose value is
an object, with no name repeated in any object, names compared exactly
once their escapes are decoded, a lone escaped surrogate malformed, the
round a number without sign, fraction or exponent from 1 to 2^53 - 1,
and signature and randomness strings, with the error texts of Go.
ParsedRelease is now a Release: no round above 2^53 - 1 is read. The
page reads the answers of the relays with it (drand.ts), as the client
of Go does, and the pasted release with strictJSON and jsonRound
(release-input.ts), so that it never reads another round than step 10.
Tests: security_cms.json with seal_reason (143 cases), the 38 JSON
inputs of release.json, the new cases of signature2_test.go and
drandjson_test.go (with the escapes written as escapes), and the new
fixtures: format3_time_and_key_words opens with the identity that the
words of its words_text give with normalizeWords and wordKey, in the
library and in the page, and format3_full_chunk, whose PAYLOAD_AGE ends
in a full STREAM chunk, opens. check-build.mjs counts words_text among
the secrets of the fixtures.
Reference files made again with Go at 4f78854: mutation-texts.json (its
spec field only), ibe-vectors.json (the two new fixtures, the rest
unchanged) and signing-vectors.json, in an export of 4f78854 with the
same frozen samples read again: the capsules are the same, and the
tokens of the sealer, without accuracy, now give S5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 day ago
|
|
|
let round: number | undefined;
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
let signature: string | undefined;
|
Specification 0.16 draft: a seal without accuracy, drand's JSON read strictly
The draft v0.16 of datekeys-go at 4f78854 (branch v0.16): SPEC_VERSION
0.16, and testdata, wordlists and annex synced from that commit. The
annex is §79 of the draft, with the CC BY-ND 4.0 license of the
specification in its title and the key of words in 79.7.
A seal without accuracy proves nothing before the opening date (§29.7,
§29.11, as 7e3b810): a valid seal is S4 only when its token carries
accuracy and t plus the accuracy is before round_time; otherwise S5,
with the first reason that holds: late, no accuracy under the BTSP
policy of ETSI EN 319 421 (0.4.0.2023.1.1), or no accuracy. cms.ts reads
hasAccuracy and the policy of the token (tokenIsBTSP); securitycms.ts
gives SealReason, Detail.sealReason and SignerLine.reason; S5 has no
fixed text any more, and verdictLines writes it and the line of a signer
of F6 with the reason, the texts of Go byte for byte (sealReasonText).
encryptFiles returns the verdicts of the area it wrote in
Encrypted.security, as Result.Security of Go, so that a writer warns of
a seal without accuracy (§62.1 rule 19).
drand's JSON is read strictly (§47.1, as b570338): parseDrandJSON, as
ParseDrandJSON of Go, reads RFC 8259 JSON in valid UTF-8 whose value is
an object, with no name repeated in any object, names compared exactly
once their escapes are decoded, a lone escaped surrogate malformed, the
round a number without sign, fraction or exponent from 1 to 2^53 - 1,
and signature and randomness strings, with the error texts of Go.
ParsedRelease is now a Release: no round above 2^53 - 1 is read. The
page reads the answers of the relays with it (drand.ts), as the client
of Go does, and the pasted release with strictJSON and jsonRound
(release-input.ts), so that it never reads another round than step 10.
Tests: security_cms.json with seal_reason (143 cases), the 38 JSON
inputs of release.json, the new cases of signature2_test.go and
drandjson_test.go (with the escapes written as escapes), and the new
fixtures: format3_time_and_key_words opens with the identity that the
words of its words_text give with normalizeWords and wordKey, in the
library and in the page, and format3_full_chunk, whose PAYLOAD_AGE ends
in a full STREAM chunk, opens. check-build.mjs counts words_text among
the secrets of the fixtures.
Reference files made again with Go at 4f78854: mutation-texts.json (its
spec field only), ibe-vectors.json (the two new fixtures, the rest
unchanged) and signing-vectors.json, in an export of 4f78854 with the
same frozen samples read again: the capsules are the same, and the
tokens of the sealer, without accuracy, now give S5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 day ago
|
|
|
let randomness: string | undefined;
|
|
|
|
|
for (const m of members) {
|
|
|
|
|
if (m.name === "round") {
|
|
|
|
|
round = jsonRound(m);
|
|
|
|
|
if (round === undefined) throw malformed();
|
|
|
|
|
} else if (m.name === "signature" || m.name === "randomness") {
|
|
|
|
|
if (m.kind !== '"') throw malformed();
|
|
|
|
|
if (m.name === "signature") signature = m.str;
|
|
|
|
|
else randomness = m.str;
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
}
|
|
|
|
|
}
|
Specification 0.16 draft: a seal without accuracy, drand's JSON read strictly
The draft v0.16 of datekeys-go at 4f78854 (branch v0.16): SPEC_VERSION
0.16, and testdata, wordlists and annex synced from that commit. The
annex is §79 of the draft, with the CC BY-ND 4.0 license of the
specification in its title and the key of words in 79.7.
A seal without accuracy proves nothing before the opening date (§29.7,
§29.11, as 7e3b810): a valid seal is S4 only when its token carries
accuracy and t plus the accuracy is before round_time; otherwise S5,
with the first reason that holds: late, no accuracy under the BTSP
policy of ETSI EN 319 421 (0.4.0.2023.1.1), or no accuracy. cms.ts reads
hasAccuracy and the policy of the token (tokenIsBTSP); securitycms.ts
gives SealReason, Detail.sealReason and SignerLine.reason; S5 has no
fixed text any more, and verdictLines writes it and the line of a signer
of F6 with the reason, the texts of Go byte for byte (sealReasonText).
encryptFiles returns the verdicts of the area it wrote in
Encrypted.security, as Result.Security of Go, so that a writer warns of
a seal without accuracy (§62.1 rule 19).
drand's JSON is read strictly (§47.1, as b570338): parseDrandJSON, as
ParseDrandJSON of Go, reads RFC 8259 JSON in valid UTF-8 whose value is
an object, with no name repeated in any object, names compared exactly
once their escapes are decoded, a lone escaped surrogate malformed, the
round a number without sign, fraction or exponent from 1 to 2^53 - 1,
and signature and randomness strings, with the error texts of Go.
ParsedRelease is now a Release: no round above 2^53 - 1 is read. The
page reads the answers of the relays with it (drand.ts), as the client
of Go does, and the pasted release with strictJSON and jsonRound
(release-input.ts), so that it never reads another round than step 10.
Tests: security_cms.json with seal_reason (143 cases), the 38 JSON
inputs of release.json, the new cases of signature2_test.go and
drandjson_test.go (with the escapes written as escapes), and the new
fixtures: format3_time_and_key_words opens with the identity that the
words of its words_text give with normalizeWords and wordKey, in the
library and in the page, and format3_full_chunk, whose PAYLOAD_AGE ends
in a full STREAM chunk, opens. check-build.mjs counts words_text among
the secrets of the fixtures.
Reference files made again with Go at 4f78854: mutation-texts.json (its
spec field only), ibe-vectors.json (the two new fixtures, the rest
unchanged) and signing-vectors.json, in an export of 4f78854 with the
same frozen samples read again: the capsules are the same, and the
tokens of the sealer, without accuracy, now give S5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 day ago
|
|
|
if (round === undefined || signature === undefined) throw malformed();
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
if (!/^([0-9a-fA-F]{2})*$/.test(signature)) {
|
|
|
|
|
throw new DateKeysError(
|
|
|
|
|
"ERR_RELEASE_INVALID",
|
|
|
|
|
"provider: drand JSON: signature is not hex",
|
|
|
|
|
);
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
}
|
Specification 0.16 draft: a seal without accuracy, drand's JSON read strictly
The draft v0.16 of datekeys-go at 4f78854 (branch v0.16): SPEC_VERSION
0.16, and testdata, wordlists and annex synced from that commit. The
annex is §79 of the draft, with the CC BY-ND 4.0 license of the
specification in its title and the key of words in 79.7.
A seal without accuracy proves nothing before the opening date (§29.7,
§29.11, as 7e3b810): a valid seal is S4 only when its token carries
accuracy and t plus the accuracy is before round_time; otherwise S5,
with the first reason that holds: late, no accuracy under the BTSP
policy of ETSI EN 319 421 (0.4.0.2023.1.1), or no accuracy. cms.ts reads
hasAccuracy and the policy of the token (tokenIsBTSP); securitycms.ts
gives SealReason, Detail.sealReason and SignerLine.reason; S5 has no
fixed text any more, and verdictLines writes it and the line of a signer
of F6 with the reason, the texts of Go byte for byte (sealReasonText).
encryptFiles returns the verdicts of the area it wrote in
Encrypted.security, as Result.Security of Go, so that a writer warns of
a seal without accuracy (§62.1 rule 19).
drand's JSON is read strictly (§47.1, as b570338): parseDrandJSON, as
ParseDrandJSON of Go, reads RFC 8259 JSON in valid UTF-8 whose value is
an object, with no name repeated in any object, names compared exactly
once their escapes are decoded, a lone escaped surrogate malformed, the
round a number without sign, fraction or exponent from 1 to 2^53 - 1,
and signature and randomness strings, with the error texts of Go.
ParsedRelease is now a Release: no round above 2^53 - 1 is read. The
page reads the answers of the relays with it (drand.ts), as the client
of Go does, and the pasted release with strictJSON and jsonRound
(release-input.ts), so that it never reads another round than step 10.
Tests: security_cms.json with seal_reason (143 cases), the 38 JSON
inputs of release.json, the new cases of signature2_test.go and
drandjson_test.go (with the escapes written as escapes), and the new
fixtures: format3_time_and_key_words opens with the identity that the
words of its words_text give with normalizeWords and wordKey, in the
library and in the page, and format3_full_chunk, whose PAYLOAD_AGE ends
in a full STREAM chunk, opens. check-build.mjs counts words_text among
the secrets of the fixtures.
Reference files made again with Go at 4f78854: mutation-texts.json (its
spec field only), ibe-vectors.json (the two new fixtures, the rest
unchanged) and signing-vectors.json, in an export of 4f78854 with the
same frozen samples read again: the capsules are the same, and the
tokens of the sealer, without accuracy, now give S5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 day ago
|
|
|
const sig = fromHex(signature);
|
|
|
|
|
if (
|
Specification 0.16 draft: a seal without accuracy, drand's JSON read strictly
The draft v0.16 of datekeys-go at 4f78854 (branch v0.16): SPEC_VERSION
0.16, and testdata, wordlists and annex synced from that commit. The
annex is §79 of the draft, with the CC BY-ND 4.0 license of the
specification in its title and the key of words in 79.7.
A seal without accuracy proves nothing before the opening date (§29.7,
§29.11, as 7e3b810): a valid seal is S4 only when its token carries
accuracy and t plus the accuracy is before round_time; otherwise S5,
with the first reason that holds: late, no accuracy under the BTSP
policy of ETSI EN 319 421 (0.4.0.2023.1.1), or no accuracy. cms.ts reads
hasAccuracy and the policy of the token (tokenIsBTSP); securitycms.ts
gives SealReason, Detail.sealReason and SignerLine.reason; S5 has no
fixed text any more, and verdictLines writes it and the line of a signer
of F6 with the reason, the texts of Go byte for byte (sealReasonText).
encryptFiles returns the verdicts of the area it wrote in
Encrypted.security, as Result.Security of Go, so that a writer warns of
a seal without accuracy (§62.1 rule 19).
drand's JSON is read strictly (§47.1, as b570338): parseDrandJSON, as
ParseDrandJSON of Go, reads RFC 8259 JSON in valid UTF-8 whose value is
an object, with no name repeated in any object, names compared exactly
once their escapes are decoded, a lone escaped surrogate malformed, the
round a number without sign, fraction or exponent from 1 to 2^53 - 1,
and signature and randomness strings, with the error texts of Go.
ParsedRelease is now a Release: no round above 2^53 - 1 is read. The
page reads the answers of the relays with it (drand.ts), as the client
of Go does, and the pasted release with strictJSON and jsonRound
(release-input.ts), so that it never reads another round than step 10.
Tests: security_cms.json with seal_reason (143 cases), the 38 JSON
inputs of release.json, the new cases of signature2_test.go and
drandjson_test.go (with the escapes written as escapes), and the new
fixtures: format3_time_and_key_words opens with the identity that the
words of its words_text give with normalizeWords and wordKey, in the
library and in the page, and format3_full_chunk, whose PAYLOAD_AGE ends
in a full STREAM chunk, opens. check-build.mjs counts words_text among
the secrets of the fixtures.
Reference files made again with Go at 4f78854: mutation-texts.json (its
spec field only), ibe-vectors.json (the two new fixtures, the rest
unchanged) and signing-vectors.json, in an export of 4f78854 with the
same frozen samples read again: the capsules are the same, and the
tokens of the sealer, without accuracy, now give S5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 day ago
|
|
|
randomness !== undefined &&
|
|
|
|
|
randomness.toLowerCase() !== toHex(await sha256(sig))
|
|
|
|
|
) {
|
|
|
|
|
throw new DateKeysError(
|
|
|
|
|
"ERR_RELEASE_INVALID",
|
|
|
|
|
"provider: drand JSON: randomness does not match the signature",
|
|
|
|
|
);
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
}
|
Specification 0.16 draft: a seal without accuracy, drand's JSON read strictly
The draft v0.16 of datekeys-go at 4f78854 (branch v0.16): SPEC_VERSION
0.16, and testdata, wordlists and annex synced from that commit. The
annex is §79 of the draft, with the CC BY-ND 4.0 license of the
specification in its title and the key of words in 79.7.
A seal without accuracy proves nothing before the opening date (§29.7,
§29.11, as 7e3b810): a valid seal is S4 only when its token carries
accuracy and t plus the accuracy is before round_time; otherwise S5,
with the first reason that holds: late, no accuracy under the BTSP
policy of ETSI EN 319 421 (0.4.0.2023.1.1), or no accuracy. cms.ts reads
hasAccuracy and the policy of the token (tokenIsBTSP); securitycms.ts
gives SealReason, Detail.sealReason and SignerLine.reason; S5 has no
fixed text any more, and verdictLines writes it and the line of a signer
of F6 with the reason, the texts of Go byte for byte (sealReasonText).
encryptFiles returns the verdicts of the area it wrote in
Encrypted.security, as Result.Security of Go, so that a writer warns of
a seal without accuracy (§62.1 rule 19).
drand's JSON is read strictly (§47.1, as b570338): parseDrandJSON, as
ParseDrandJSON of Go, reads RFC 8259 JSON in valid UTF-8 whose value is
an object, with no name repeated in any object, names compared exactly
once their escapes are decoded, a lone escaped surrogate malformed, the
round a number without sign, fraction or exponent from 1 to 2^53 - 1,
and signature and randomness strings, with the error texts of Go.
ParsedRelease is now a Release: no round above 2^53 - 1 is read. The
page reads the answers of the relays with it (drand.ts), as the client
of Go does, and the pasted release with strictJSON and jsonRound
(release-input.ts), so that it never reads another round than step 10.
Tests: security_cms.json with seal_reason (143 cases), the 38 JSON
inputs of release.json, the new cases of signature2_test.go and
drandjson_test.go (with the escapes written as escapes), and the new
fixtures: format3_time_and_key_words opens with the identity that the
words of its words_text give with normalizeWords and wordKey, in the
library and in the page, and format3_full_chunk, whose PAYLOAD_AGE ends
in a full STREAM chunk, opens. check-build.mjs counts words_text among
the secrets of the fixtures.
Reference files made again with Go at 4f78854: mutation-texts.json (its
spec field only), ibe-vectors.json (the two new fixtures, the rest
unchanged) and signing-vectors.json, in an export of 4f78854 with the
same frozen samples read again: the capsules are the same, and the
tokens of the sealer, without accuracy, now give S5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 day ago
|
|
|
return { round, signature: sig };
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The release object of a release of the profile `p`, with the chain hash
|
|
|
|
|
* of `p`, as provider.NewReleaseObject: what a reader would keep after
|
|
|
|
|
* verifying the release (spec v0.15, §47.1).
|
|
|
|
|
*/
|
|
|
|
|
export function newReleaseObject(p: Profile, r: Release): Uint8Array {
|
|
|
|
|
return encodeRelease({
|
|
|
|
|
round: r.round,
|
|
|
|
|
signature: r.signature,
|
|
|
|
|
chainHash: p.chainHash,
|
|
|
|
|
});
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// A release in the caller's hand
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A release that the caller has in hand (spec v0.15, §49, §63 step 9.c), as
|
|
|
|
|
* provider.Supplier: a release object read from a file, drand's JSON that
|
|
|
|
|
* the person saved, or an entry of a local archive. It makes no network
|
|
|
|
|
* request, so open asks it for the release without comparing its clock with
|
|
|
|
|
* the round time: a valid signature proves that the round was published.
|
|
|
|
|
*
|
|
|
|
|
* `supply` returns the encoding of the release of `round`, as it is: a
|
|
|
|
|
* release object or drand's JSON, which open decodes and verifies at step
|
|
|
|
|
* 10 with the codes of that step. Without a release for `round` it throws
|
|
|
|
|
* ERR_RELEASE_UNAVAILABLE, the code of step 9.
|
|
|
|
|
*/
|
|
|
|
|
export interface ReleaseSupplier {
|
|
|
|
|
supply(p: Profile, round: number): Promise<Uint8Array>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A release in hand, already read, as provider.Encoded: the bytes of a
|
|
|
|
|
* release object or of drand's JSON. It supplies itself whatever the round;
|
|
|
|
|
* step 10 compares its round with the DateKey.
|
|
|
|
|
*/
|
|
|
|
|
export function encodedRelease(b: Uint8Array): ReleaseSupplier {
|
|
|
|
|
return { supply: () => Promise.resolve(b) };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// A local release archive (informative, spec v0.15, §50)
|
|
|
|
|
|
|
|
|
|
// The text of what a read threw, for an error of the archive.
|
|
|
|
|
const errText = (err: unknown): string =>
|
|
|
|
|
err instanceof Error ? err.message : String(err);
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
|
|
|
|
|
interface ArchiveHeader {
|
|
|
|
|
chainHash: Uint8Array;
|
|
|
|
|
first: number;
|
|
|
|
|
count: number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function encodeArchiveWire(e: Encoder, h: ArchiveHeader): void {
|
|
|
|
|
e.map(ARCHIVE_KEYS);
|
|
|
|
|
e.uint(0);
|
|
|
|
|
e.text(ARCHIVE_TYPE_TAG);
|
|
|
|
|
e.uint(1);
|
|
|
|
|
e.uint(ARCHIVE_SCHEMA_VERSION);
|
|
|
|
|
e.uint(2);
|
|
|
|
|
e.bstr(h.chainHash);
|
|
|
|
|
e.uint(3);
|
|
|
|
|
e.uint(h.first);
|
|
|
|
|
e.uint(4);
|
|
|
|
|
e.uint(h.count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The header decoder of the reference, whose own failures carry no code: the
|
|
|
|
|
// format is informative, and every failure is ERR_RELEASE_UNAVAILABLE.
|
|
|
|
|
function decodeArchiveWire(d: Decoder): ArchiveHeader {
|
|
|
|
|
const h: ArchiveHeader = { chainHash: new Uint8Array(0), first: 0, count: 0 };
|
|
|
|
|
const pairs = d.map(ARCHIVE_KEYS);
|
|
|
|
|
if (pairs !== ARCHIVE_KEYS)
|
|
|
|
|
throw new Error(`${pairs} keys, want all ${ARCHIVE_KEYS}`);
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
for (let want = 0; want < ARCHIVE_KEYS; want++) {
|
|
|
|
|
const k = d.key();
|
|
|
|
|
if (k !== want) throw new Error(`key ${k} where key ${want} was expected`);
|
|
|
|
|
try {
|
|
|
|
|
switch (want) {
|
|
|
|
|
case 0:
|
|
|
|
|
d.text(utf8Length(ARCHIVE_TYPE_TAG));
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
d.uint(ARCHIVE_SCHEMA_VERSION);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
h.chainHash = d.bstr(32, 32);
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
h.first = d.uint(MAX_SAFE_UINT);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
h.count = d.uint(MAX_SAFE_UINT);
|
|
|
|
|
}
|
|
|
|
|
} catch (err) {
|
|
|
|
|
/* v8 ignore next -- @preserve: the decoder throws only DateKeysError */
|
|
|
|
|
throw new Error(`key ${k}: ${errText(err)}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
d.endMap();
|
|
|
|
|
return h;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The header of an archive of `count` rounds of the chain `chainHash` from
|
|
|
|
|
* the round `first` (spec v0.15, §50), as provider.EncodeArchiveHeader. The
|
|
|
|
|
* signatures follow it, one after another, each with the length of a
|
|
|
|
|
* signature of the chain, and a round the archive lacks is written as zeros.
|
|
|
|
|
*/
|
|
|
|
|
export function encodeArchiveHeader(
|
|
|
|
|
chainHash: Uint8Array,
|
|
|
|
|
first: number,
|
|
|
|
|
count: number,
|
|
|
|
|
): Uint8Array {
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
if (
|
|
|
|
|
chainHash.length !== 32 ||
|
|
|
|
|
!Number.isSafeInteger(first) ||
|
|
|
|
|
!Number.isSafeInteger(count) ||
|
|
|
|
|
first < 1 ||
|
|
|
|
|
count < 1 ||
|
|
|
|
|
first > MAX_SAFE_UINT - count + 1
|
|
|
|
|
) {
|
|
|
|
|
throw new Error(
|
|
|
|
|
`provider: archive header: chain hash of ${chainHash.length} bytes, rounds ${first} to ${first} + ${count} - 1`,
|
|
|
|
|
);
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
}
|
|
|
|
|
const e = new Encoder();
|
|
|
|
|
encodeArchiveWire(e, { chainHash, first, count });
|
|
|
|
|
return e.out();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Reports whether `b`, the start of a file, is the start of a release archive. */
|
|
|
|
|
export function isReleaseArchive(b: Uint8Array): boolean {
|
|
|
|
|
try {
|
|
|
|
|
return peek(b).typeTag === ARCHIVE_TYPE_TAG;
|
|
|
|
|
} catch {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A local release archive, the informative format of spec v0.15, §50, as
|
|
|
|
|
* provider.Archive: a header in deterministic CBOR, {0:
|
|
|
|
|
* "datekeys-release-archive", 1: 1, 2: chain_hash, 3: first round, 4: number
|
|
|
|
|
* of rounds}, followed by the signatures, so that the one of round r starts
|
|
|
|
|
* at the end of the header plus (r - first)·n, with n the length of a
|
|
|
|
|
* signature of the chain, 48 bytes in Quicknet. A round written as zeros is
|
|
|
|
|
* missing.
|
|
|
|
|
*
|
|
|
|
|
* A local archive is a release in hand: its entry is decoded and verified at
|
|
|
|
|
* step 10 like a release object. A round it lacks, a header it cannot read,
|
|
|
|
|
* an archive of another chain or of another length are failures to supply a
|
|
|
|
|
* release, ERR_RELEASE_UNAVAILABLE at step 9: the format has no codes of its
|
|
|
|
|
* own. Of a Blob only the header and one signature are read.
|
|
|
|
|
*/
|
|
|
|
|
export class ReleaseArchive implements ReleaseSupplier {
|
|
|
|
|
readonly #data: Uint8Array | Blob;
|
|
|
|
|
|
|
|
|
|
constructor(data: Uint8Array | Blob) {
|
|
|
|
|
this.#data = data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async #read(start: number, length: number): Promise<Uint8Array> {
|
|
|
|
|
const d = this.#data;
|
|
|
|
|
if (d instanceof Uint8Array) return d.subarray(start, start + length);
|
|
|
|
|
return new Uint8Array(await d.slice(start, start + length).arrayBuffer());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async supply(p: Profile, round: number): Promise<Uint8Array> {
|
|
|
|
|
const unavailable = (detail: string): DateKeysError =>
|
|
|
|
|
new DateKeysError(
|
|
|
|
|
"ERR_RELEASE_UNAVAILABLE",
|
|
|
|
|
`provider: release archive: ${detail}`,
|
|
|
|
|
);
|
|
|
|
|
const size =
|
|
|
|
|
this.#data instanceof Uint8Array ? this.#data.length : this.#data.size;
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
let head: Uint8Array;
|
|
|
|
|
try {
|
|
|
|
|
head = await this.#read(0, Math.min(size, MAX_ARCHIVE_HEADER));
|
|
|
|
|
} catch (err) {
|
|
|
|
|
throw unavailable(errText(err));
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
checkSchema(head, ARCHIVE_TYPE_TAG, ARCHIVE_SCHEMA_VERSION);
|
|
|
|
|
} catch {
|
|
|
|
|
throw unavailable(`not an archive of version ${ARCHIVE_SCHEMA_VERSION}`);
|
|
|
|
|
}
|
|
|
|
|
let h: ArchiveHeader;
|
|
|
|
|
try {
|
|
|
|
|
h = decodeArchiveWire(new Decoder(head));
|
|
|
|
|
} catch (err) {
|
|
|
|
|
throw unavailable(`its header does not decode: ${errText(err)}`);
|
|
|
|
|
}
|
|
|
|
|
// The header is the deterministic encoding of what it says: its length
|
|
|
|
|
// is that of the encoding, and the signatures follow it. The strict
|
|
|
|
|
// decoder already refuses any other encoding; the check is the one of
|
|
|
|
|
// the reference.
|
|
|
|
|
const e = new Encoder();
|
|
|
|
|
encodeArchiveWire(e, h);
|
|
|
|
|
const enc = e.out();
|
|
|
|
|
/* v8 ignore next 3 -- @preserve: what the strict decoder read encodes back to the same bytes */
|
|
|
|
|
if (!equalBytes(enc, head.subarray(0, Math.min(enc.length, head.length)))) {
|
|
|
|
|
throw unavailable(
|
|
|
|
|
"its header is not the deterministic encoding of its value",
|
|
|
|
|
);
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
}
|
|
|
|
|
if (!equalBytes(h.chainHash, p.chainHash)) {
|
|
|
|
|
throw unavailable(
|
|
|
|
|
`archive of chain ${toHex(h.chainHash)}, the pinned profile ${p.id} is chain ${toHex(p.chainHash)}`,
|
|
|
|
|
);
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
}
|
|
|
|
|
if (
|
|
|
|
|
h.first === 0 ||
|
|
|
|
|
h.count === 0 ||
|
|
|
|
|
round < h.first ||
|
|
|
|
|
round - h.first >= h.count
|
|
|
|
|
) {
|
|
|
|
|
throw unavailable(
|
|
|
|
|
`round ${round} is not in the archive, which holds ${h.count} rounds from ${h.first}`,
|
|
|
|
|
);
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
}
|
|
|
|
|
if (p.provider !== "drand")
|
|
|
|
|
throw unavailable(
|
|
|
|
|
`profile ${p.id}: provider ${goQuote(p.provider)} is not drand: ERR_UNKNOWN_PROFILE`,
|
|
|
|
|
);
|
|
|
|
|
if (p.scheme !== QUICKNET_SCHEME)
|
|
|
|
|
throw unavailable(
|
|
|
|
|
`profile ${p.id}: ${goQuote(p.scheme)} is not a drand scheme: ERR_UNKNOWN_PROFILE`,
|
|
|
|
|
);
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
const n = QUICKNET_SIGNATURE_LEN;
|
|
|
|
|
const want = BigInt(enc.length) + BigInt(h.count) * BigInt(n);
|
|
|
|
|
if (BigInt(h.count) > (1n << 62n) / BigInt(n) || BigInt(size) !== want) {
|
|
|
|
|
throw unavailable(
|
|
|
|
|
`${size} bytes, its header announces ${h.count} rounds of ${n} bytes`,
|
|
|
|
|
);
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
}
|
|
|
|
|
let sig: Uint8Array;
|
|
|
|
|
try {
|
|
|
|
|
sig = await this.#read(enc.length + (round - h.first) * n, n);
|
|
|
|
|
} catch (err) {
|
|
|
|
|
throw unavailable(errText(err));
|
|
|
|
|
}
|
|
|
|
|
if (sig.every((x) => x === 0))
|
|
|
|
|
throw unavailable(`round ${round} is missing: its entry is zeros`);
|
Specification 0.15: the release object, a release in hand and step 9.c
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
|
|
|
return encodeRelease({ chainHash: h.chainHash, round, signature: sig });
|
|
|
|
|
}
|
|
|
|
|
}
|