@noeos/verification-engine 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/LICENSE +201 -0
- package/NOTICE +11 -0
- package/README.md +7 -0
- package/dist/cjs/api/engine.js +271 -0
- package/dist/cjs/api/types.js +10 -0
- package/dist/cjs/chains/chain-builder.js +541 -0
- package/dist/cjs/chains/duplicate-detector.js +208 -0
- package/dist/cjs/chains/verify-chain.js +656 -0
- package/dist/cjs/contracts/generated.js +512 -0
- package/dist/cjs/contracts/schema-assets.js +6 -0
- package/dist/cjs/contracts/vector-assets.js +6 -0
- package/dist/cjs/domain/algorithm-id.js +5 -0
- package/dist/cjs/domain/byte-view.js +7 -0
- package/dist/cjs/domain/chain.js +3 -0
- package/dist/cjs/domain/diagnostic.js +6 -0
- package/dist/cjs/domain/digest.js +37 -0
- package/dist/cjs/domain/duplicate-policy.js +3 -0
- package/dist/cjs/domain/evidence.js +10 -0
- package/dist/cjs/domain/identifiers.js +52 -0
- package/dist/cjs/domain/json-value.js +3 -0
- package/dist/cjs/domain/limits.js +24 -0
- package/dist/cjs/domain/operation-result.js +19 -0
- package/dist/cjs/domain/position.js +16 -0
- package/dist/cjs/domain/protocol-version.js +5 -0
- package/dist/cjs/domain/rule.js +3 -0
- package/dist/cjs/domain/stream.js +3 -0
- package/dist/cjs/domain/version.js +16 -0
- package/dist/cjs/evidence/digest-evidence.js +22 -0
- package/dist/cjs/evidence/evidence-parser.js +288 -0
- package/dist/cjs/framing/frame-builders.js +124 -0
- package/dist/cjs/framing/frame-encoder.js +238 -0
- package/dist/cjs/framing/frame-parser.js +173 -0
- package/dist/cjs/framing/frame-types.js +3 -0
- package/dist/cjs/hashing/hash-adapter.js +90 -0
- package/dist/cjs/hashing/hash-frame.js +16 -0
- package/dist/cjs/index.js +16 -0
- package/dist/cjs/normalization/byte-sink.js +70 -0
- package/dist/cjs/normalization/jcs-profile.js +154 -0
- package/dist/cjs/normalization/normalize.js +56 -0
- package/dist/cjs/normalization/profile-registry.js +66 -0
- package/dist/cjs/normalization/profile.js +3 -0
- package/dist/cjs/normalization/raw-bytes-profile.js +27 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/profiles.js +9 -0
- package/dist/cjs/records/record-service.js +278 -0
- package/dist/cjs/rules/rule-set.js +211 -0
- package/dist/cjs/schemas.js +6 -0
- package/dist/cjs/validation/algorithm-validation.js +12 -0
- package/dist/cjs/validation/diagnostic-collector.js +159 -0
- package/dist/cjs/validation/digest-validation.js +48 -0
- package/dist/cjs/validation/identifier-validation.js +33 -0
- package/dist/cjs/validation/json-text-parser.js +297 -0
- package/dist/cjs/validation/json-value-validation.js +155 -0
- package/dist/cjs/validation/limit-validation.js +75 -0
- package/dist/cjs/validation/object-inspection.js +60 -0
- package/dist/cjs/validation/position-validation.js +13 -0
- package/dist/cjs/validation/result-helpers.js +9 -0
- package/dist/cjs/validation/utf8-validation.js +69 -0
- package/dist/cjs/validation/version-validation.js +31 -0
- package/dist/cjs/vectors.js +6 -0
- package/dist/esm/api/engine.js +266 -0
- package/dist/esm/api/types.js +4 -0
- package/dist/esm/chains/chain-builder.js +536 -0
- package/dist/esm/chains/duplicate-detector.js +204 -0
- package/dist/esm/chains/verify-chain.js +652 -0
- package/dist/esm/contracts/generated.js +509 -0
- package/dist/esm/contracts/schema-assets.js +2 -0
- package/dist/esm/contracts/vector-assets.js +2 -0
- package/dist/esm/domain/algorithm-id.js +2 -0
- package/dist/esm/domain/byte-view.js +4 -0
- package/dist/esm/domain/chain.js +2 -0
- package/dist/esm/domain/diagnostic.js +3 -0
- package/dist/esm/domain/digest.js +32 -0
- package/dist/esm/domain/duplicate-policy.js +2 -0
- package/dist/esm/domain/evidence.js +7 -0
- package/dist/esm/domain/identifiers.js +45 -0
- package/dist/esm/domain/json-value.js +2 -0
- package/dist/esm/domain/limits.js +21 -0
- package/dist/esm/domain/operation-result.js +15 -0
- package/dist/esm/domain/position.js +12 -0
- package/dist/esm/domain/protocol-version.js +2 -0
- package/dist/esm/domain/rule.js +2 -0
- package/dist/esm/domain/stream.js +2 -0
- package/dist/esm/domain/version.js +12 -0
- package/dist/esm/evidence/digest-evidence.js +19 -0
- package/dist/esm/evidence/evidence-parser.js +281 -0
- package/dist/esm/framing/frame-builders.js +114 -0
- package/dist/esm/framing/frame-encoder.js +234 -0
- package/dist/esm/framing/frame-parser.js +170 -0
- package/dist/esm/framing/frame-types.js +2 -0
- package/dist/esm/hashing/hash-adapter.js +84 -0
- package/dist/esm/hashing/hash-frame.js +12 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/normalization/byte-sink.js +66 -0
- package/dist/esm/normalization/jcs-profile.js +151 -0
- package/dist/esm/normalization/normalize.js +52 -0
- package/dist/esm/normalization/profile-registry.js +62 -0
- package/dist/esm/normalization/profile.js +2 -0
- package/dist/esm/normalization/raw-bytes-profile.js +24 -0
- package/dist/esm/profiles.js +6 -0
- package/dist/esm/records/record-service.js +270 -0
- package/dist/esm/rules/rule-set.js +206 -0
- package/dist/esm/schemas.js +2 -0
- package/dist/esm/validation/algorithm-validation.js +9 -0
- package/dist/esm/validation/diagnostic-collector.js +154 -0
- package/dist/esm/validation/digest-validation.js +43 -0
- package/dist/esm/validation/identifier-validation.js +27 -0
- package/dist/esm/validation/json-text-parser.js +294 -0
- package/dist/esm/validation/json-value-validation.js +152 -0
- package/dist/esm/validation/limit-validation.js +71 -0
- package/dist/esm/validation/object-inspection.js +54 -0
- package/dist/esm/validation/position-validation.js +10 -0
- package/dist/esm/validation/result-helpers.js +6 -0
- package/dist/esm/validation/utf8-validation.js +63 -0
- package/dist/esm/validation/version-validation.js +26 -0
- package/dist/esm/vectors.js +2 -0
- package/dist/types/api/engine.d.ts +8 -0
- package/dist/types/api/types.d.ts +124 -0
- package/dist/types/chains/chain-builder.d.ts +42 -0
- package/dist/types/chains/duplicate-detector.d.ts +18 -0
- package/dist/types/chains/verify-chain.d.ts +9 -0
- package/dist/types/contracts/generated.d.ts +442 -0
- package/dist/types/contracts/schema-assets.d.ts +2 -0
- package/dist/types/contracts/vector-assets.d.ts +2 -0
- package/dist/types/domain/algorithm-id.d.ts +4 -0
- package/dist/types/domain/byte-view.d.ts +1 -0
- package/dist/types/domain/chain.d.ts +43 -0
- package/dist/types/domain/diagnostic.d.ts +23 -0
- package/dist/types/domain/digest.d.ts +12 -0
- package/dist/types/domain/duplicate-policy.d.ts +26 -0
- package/dist/types/domain/evidence.d.ts +100 -0
- package/dist/types/domain/identifiers.d.ts +29 -0
- package/dist/types/domain/json-value.d.ts +6 -0
- package/dist/types/domain/limits.d.ts +13 -0
- package/dist/types/domain/operation-result.d.ts +12 -0
- package/dist/types/domain/position.d.ts +8 -0
- package/dist/types/domain/protocol-version.d.ts +2 -0
- package/dist/types/domain/rule.d.ts +34 -0
- package/dist/types/domain/stream.d.ts +5 -0
- package/dist/types/domain/version.d.ts +8 -0
- package/dist/types/evidence/digest-evidence.d.ts +4 -0
- package/dist/types/evidence/evidence-parser.d.ts +8 -0
- package/dist/types/framing/frame-builders.d.ts +40 -0
- package/dist/types/framing/frame-encoder.d.ts +6 -0
- package/dist/types/framing/frame-parser.d.ts +4 -0
- package/dist/types/framing/frame-types.d.ts +27 -0
- package/dist/types/hashing/hash-adapter.d.ts +12 -0
- package/dist/types/hashing/hash-frame.d.ts +6 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/normalization/byte-sink.d.ts +19 -0
- package/dist/types/normalization/jcs-profile.d.ts +3 -0
- package/dist/types/normalization/normalize.d.ts +11 -0
- package/dist/types/normalization/profile-registry.d.ts +26 -0
- package/dist/types/normalization/profile.d.ts +22 -0
- package/dist/types/normalization/raw-bytes-profile.d.ts +2 -0
- package/dist/types/profiles.d.ts +8 -0
- package/dist/types/records/record-service.d.ts +38 -0
- package/dist/types/rules/rule-set.d.ts +13 -0
- package/dist/types/schemas.d.ts +2 -0
- package/dist/types/validation/algorithm-validation.d.ts +3 -0
- package/dist/types/validation/diagnostic-collector.d.ts +24 -0
- package/dist/types/validation/digest-validation.d.ts +6 -0
- package/dist/types/validation/identifier-validation.d.ts +6 -0
- package/dist/types/validation/json-text-parser.d.ts +4 -0
- package/dist/types/validation/json-value-validation.d.ts +4 -0
- package/dist/types/validation/limit-validation.d.ts +4 -0
- package/dist/types/validation/object-inspection.d.ts +11 -0
- package/dist/types/validation/position-validation.d.ts +3 -0
- package/dist/types/validation/result-helpers.d.ts +3 -0
- package/dist/types/validation/utf8-validation.d.ts +5 -0
- package/dist/types/validation/version-validation.d.ts +9 -0
- package/dist/types/vectors.d.ts +2 -0
- package/package.json +61 -0
- package/schemas/chain-summary.v1.schema.json +156 -0
- package/schemas/diagnostic.v1.schema.json +107 -0
- package/schemas/link-evidence.v1.schema.json +165 -0
- package/schemas/record-evidence.v1.schema.json +91 -0
- package/schemas/vector-set.v1.schema.json +52 -0
- package/vectors/evidence.json +26 -0
- package/vectors/framing.json +136 -0
- package/vectors/hashing.json +58 -0
- package/vectors/invalid.json +56 -0
- package/vectors/manifest.json +46 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
const profileVersionBrand = Symbol("ProfileVersion");
|
|
3
|
+
export class ProfileVersion {
|
|
4
|
+
value;
|
|
5
|
+
[profileVersionBrand] = true;
|
|
6
|
+
constructor(value) {
|
|
7
|
+
this.value = value;
|
|
8
|
+
}
|
|
9
|
+
static fromValidated(value) {
|
|
10
|
+
return Object.freeze(new ProfileVersion(value));
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { buildTrustedEvidenceFrame } from "../framing/frame-builders.js";
|
|
3
|
+
import { hashTrustedFrame } from "../hashing/hash-frame.js";
|
|
4
|
+
import { jcsProfile } from "../normalization/jcs-profile.js";
|
|
5
|
+
import { normalizeToBytes } from "../normalization/normalize.js";
|
|
6
|
+
import { parseEvidence } from "./evidence-parser.js";
|
|
7
|
+
export function digestEvidence(value, limits) {
|
|
8
|
+
const evidence = parseEvidence(value, limits);
|
|
9
|
+
if (!evidence.ok)
|
|
10
|
+
return evidence;
|
|
11
|
+
const normalized = normalizeToBytes(jcsProfile, evidence.value, limits);
|
|
12
|
+
if (!normalized.ok)
|
|
13
|
+
return normalized;
|
|
14
|
+
return hashTrustedFrame(evidence.value.algorithm, buildTrustedEvidenceFrame({
|
|
15
|
+
algorithm: evidence.value.algorithm,
|
|
16
|
+
schemaUrn: evidence.value.$schema,
|
|
17
|
+
evidenceJcsBytes: normalized.value.bytes,
|
|
18
|
+
}, limits));
|
|
19
|
+
}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { CHAIN_SUMMARY_EVIDENCE_SCHEMA, LINK_EVIDENCE_SCHEMA, RECORD_EVIDENCE_SCHEMA, } from "../domain/evidence.js";
|
|
3
|
+
import { failure, success } from "../domain/operation-result.js";
|
|
4
|
+
import { validateAlgorithmId } from "../validation/algorithm-validation.js";
|
|
5
|
+
import { DiagnosticCollector } from "../validation/diagnostic-collector.js";
|
|
6
|
+
import { validateDigest } from "../validation/digest-validation.js";
|
|
7
|
+
import { validateContextId, validateRecordId, validateSequenceId, } from "../validation/identifier-validation.js";
|
|
8
|
+
import { parseJsonText } from "../validation/json-text-parser.js";
|
|
9
|
+
import { inspectPlainObject } from "../validation/object-inspection.js";
|
|
10
|
+
import { validatePosition } from "../validation/position-validation.js";
|
|
11
|
+
import { validateProtocolVersion } from "../validation/version-validation.js";
|
|
12
|
+
import { validateProfile } from "../records/record-service.js";
|
|
13
|
+
export function parseEvidence(value, limits) {
|
|
14
|
+
const entries = inspectPlainObject(value);
|
|
15
|
+
if (entries === undefined)
|
|
16
|
+
return evidenceFailure("EVIDENCE_INVALID", limits);
|
|
17
|
+
const schema = new Map(entries).get("$schema");
|
|
18
|
+
if (schema === RECORD_EVIDENCE_SCHEMA)
|
|
19
|
+
return parseRecordEvidence(value, limits);
|
|
20
|
+
if (schema === LINK_EVIDENCE_SCHEMA)
|
|
21
|
+
return parseLinkEvidence(value, limits);
|
|
22
|
+
if (schema === CHAIN_SUMMARY_EVIDENCE_SCHEMA)
|
|
23
|
+
return parseChainSummaryEvidence(value, limits);
|
|
24
|
+
return evidenceFailure("EVIDENCE_SCHEMA_UNKNOWN", limits);
|
|
25
|
+
}
|
|
26
|
+
export function parseEvidenceText(value, limits) {
|
|
27
|
+
const parsed = parseJsonText(value, limits);
|
|
28
|
+
if (!parsed.ok)
|
|
29
|
+
return parsed;
|
|
30
|
+
return parseEvidence(parsed.value, limits);
|
|
31
|
+
}
|
|
32
|
+
export function parseRecordEvidence(value, limits) {
|
|
33
|
+
const fields = strictFields(value, [
|
|
34
|
+
"$schema",
|
|
35
|
+
"protocolVersion",
|
|
36
|
+
"contextId",
|
|
37
|
+
"recordId",
|
|
38
|
+
"profile",
|
|
39
|
+
"algorithm",
|
|
40
|
+
"normalizedByteLength",
|
|
41
|
+
"contentDigest",
|
|
42
|
+
"recordDigest",
|
|
43
|
+
]);
|
|
44
|
+
if (fields?.get("$schema") !== RECORD_EVIDENCE_SCHEMA) {
|
|
45
|
+
return evidenceFailure("EVIDENCE_INVALID", limits);
|
|
46
|
+
}
|
|
47
|
+
const common = parseRecordFields(fields, limits);
|
|
48
|
+
if (!common.ok)
|
|
49
|
+
return common;
|
|
50
|
+
return success(Object.freeze({ $schema: RECORD_EVIDENCE_SCHEMA, ...common.value }));
|
|
51
|
+
}
|
|
52
|
+
export function parseLinkEvidence(value, limits) {
|
|
53
|
+
const fields = strictFields(value, [
|
|
54
|
+
"$schema",
|
|
55
|
+
"protocolVersion",
|
|
56
|
+
"contextId",
|
|
57
|
+
"sequenceId",
|
|
58
|
+
"position",
|
|
59
|
+
"recordId",
|
|
60
|
+
"profile",
|
|
61
|
+
"algorithm",
|
|
62
|
+
"normalizedByteLength",
|
|
63
|
+
"contentDigest",
|
|
64
|
+
"recordDigest",
|
|
65
|
+
"previous",
|
|
66
|
+
"linkDigest",
|
|
67
|
+
]);
|
|
68
|
+
if (fields?.get("$schema") !== LINK_EVIDENCE_SCHEMA) {
|
|
69
|
+
return evidenceFailure("EVIDENCE_INVALID", limits);
|
|
70
|
+
}
|
|
71
|
+
const common = parseRecordFields(fields, limits);
|
|
72
|
+
const sequenceId = validateSequenceId(fields.get("sequenceId"));
|
|
73
|
+
const position = validatePosition(fields.get("position"));
|
|
74
|
+
if (!common.ok)
|
|
75
|
+
return common;
|
|
76
|
+
if (!sequenceId.ok)
|
|
77
|
+
return evidenceFailure("EVIDENCE_INVALID", limits);
|
|
78
|
+
if (!position.ok)
|
|
79
|
+
return evidenceFailure("EVIDENCE_INVALID", limits);
|
|
80
|
+
const previous = parsePrevious(fields.get("previous"), common.value.algorithm, limits);
|
|
81
|
+
const linkDigest = validateDigest(fields.get("linkDigest"), common.value.algorithm);
|
|
82
|
+
if (!previous.ok || !linkDigest.ok)
|
|
83
|
+
return evidenceFailure("EVIDENCE_INVALID", limits);
|
|
84
|
+
if ((position.value.value === 0) !== (previous.value.kind === "none")) {
|
|
85
|
+
return evidenceFailure("EVIDENCE_INVALID", limits);
|
|
86
|
+
}
|
|
87
|
+
return success(Object.freeze({
|
|
88
|
+
$schema: LINK_EVIDENCE_SCHEMA,
|
|
89
|
+
...common.value,
|
|
90
|
+
sequenceId: sequenceId.value.value,
|
|
91
|
+
position: position.value.value,
|
|
92
|
+
previous: previous.value,
|
|
93
|
+
linkDigest: linkDigest.value.toHex(),
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
export function parseChainSummaryEvidence(value, limits) {
|
|
97
|
+
const fields = strictFields(value, [
|
|
98
|
+
"$schema",
|
|
99
|
+
"protocolVersion",
|
|
100
|
+
"contextId",
|
|
101
|
+
"sequenceId",
|
|
102
|
+
"profile",
|
|
103
|
+
"algorithm",
|
|
104
|
+
"count",
|
|
105
|
+
"firstPosition",
|
|
106
|
+
"lastPosition",
|
|
107
|
+
"firstLinkDigest",
|
|
108
|
+
"finalLinkDigest",
|
|
109
|
+
"boundaries",
|
|
110
|
+
"status",
|
|
111
|
+
"diagnostics",
|
|
112
|
+
], true);
|
|
113
|
+
if (fields?.get("$schema") !== CHAIN_SUMMARY_EVIDENCE_SCHEMA) {
|
|
114
|
+
return evidenceFailure("EVIDENCE_INVALID", limits);
|
|
115
|
+
}
|
|
116
|
+
const protocol = validateProtocolVersion(fields.get("protocolVersion"));
|
|
117
|
+
const contextId = validateContextId(fields.get("contextId"));
|
|
118
|
+
const sequenceId = validateSequenceId(fields.get("sequenceId"));
|
|
119
|
+
const profile = validateProfile(fields.get("profile"), limits);
|
|
120
|
+
const algorithm = validateAlgorithmId(fields.get("algorithm"));
|
|
121
|
+
const count = validateNonNegativeSafeInteger(fields.get("count"));
|
|
122
|
+
const boundaries = parseBoundaries(fields.get("boundaries"));
|
|
123
|
+
const status = fields.get("status");
|
|
124
|
+
const diagnostics = parseDiagnosticSummary(fields.get("diagnostics"));
|
|
125
|
+
if (!protocol.ok ||
|
|
126
|
+
!contextId.ok ||
|
|
127
|
+
!sequenceId.ok ||
|
|
128
|
+
!profile.ok ||
|
|
129
|
+
!algorithm.ok ||
|
|
130
|
+
count === undefined ||
|
|
131
|
+
boundaries === undefined ||
|
|
132
|
+
!isStatus(status) ||
|
|
133
|
+
diagnostics === undefined) {
|
|
134
|
+
return evidenceFailure("EVIDENCE_INVALID", limits);
|
|
135
|
+
}
|
|
136
|
+
if (count === 0) {
|
|
137
|
+
if (fields.has("firstPosition") ||
|
|
138
|
+
fields.has("lastPosition") ||
|
|
139
|
+
fields.has("firstLinkDigest") ||
|
|
140
|
+
fields.has("finalLinkDigest"))
|
|
141
|
+
return evidenceFailure("EVIDENCE_INVALID", limits);
|
|
142
|
+
return success(Object.freeze({
|
|
143
|
+
$schema: CHAIN_SUMMARY_EVIDENCE_SCHEMA,
|
|
144
|
+
protocolVersion: 1,
|
|
145
|
+
contextId: contextId.value.value,
|
|
146
|
+
sequenceId: sequenceId.value.value,
|
|
147
|
+
profile: profile.value,
|
|
148
|
+
algorithm: algorithm.value,
|
|
149
|
+
count,
|
|
150
|
+
boundaries,
|
|
151
|
+
status,
|
|
152
|
+
diagnostics,
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
155
|
+
if (!fields.has("firstPosition") ||
|
|
156
|
+
!fields.has("lastPosition") ||
|
|
157
|
+
!fields.has("firstLinkDigest") ||
|
|
158
|
+
!fields.has("finalLinkDigest"))
|
|
159
|
+
return evidenceFailure("EVIDENCE_INVALID", limits);
|
|
160
|
+
const firstPosition = validateNonNegativeSafeInteger(fields.get("firstPosition"));
|
|
161
|
+
const lastPosition = validateNonNegativeSafeInteger(fields.get("lastPosition"));
|
|
162
|
+
const firstDigest = validateDigest(fields.get("firstLinkDigest"), algorithm.value);
|
|
163
|
+
const finalDigest = validateDigest(fields.get("finalLinkDigest"), algorithm.value);
|
|
164
|
+
if (firstPosition === undefined ||
|
|
165
|
+
lastPosition === undefined ||
|
|
166
|
+
firstPosition > lastPosition ||
|
|
167
|
+
!firstDigest.ok ||
|
|
168
|
+
!finalDigest.ok)
|
|
169
|
+
return evidenceFailure("EVIDENCE_INVALID", limits);
|
|
170
|
+
return success(Object.freeze({
|
|
171
|
+
$schema: CHAIN_SUMMARY_EVIDENCE_SCHEMA,
|
|
172
|
+
protocolVersion: 1,
|
|
173
|
+
contextId: contextId.value.value,
|
|
174
|
+
sequenceId: sequenceId.value.value,
|
|
175
|
+
profile: profile.value,
|
|
176
|
+
algorithm: algorithm.value,
|
|
177
|
+
count,
|
|
178
|
+
firstPosition,
|
|
179
|
+
lastPosition,
|
|
180
|
+
firstLinkDigest: firstDigest.value.toHex(),
|
|
181
|
+
finalLinkDigest: finalDigest.value.toHex(),
|
|
182
|
+
boundaries,
|
|
183
|
+
status,
|
|
184
|
+
diagnostics,
|
|
185
|
+
}));
|
|
186
|
+
}
|
|
187
|
+
function parseRecordFields(fields, limits) {
|
|
188
|
+
const protocol = validateProtocolVersion(fields.get("protocolVersion"));
|
|
189
|
+
const contextId = validateContextId(fields.get("contextId"));
|
|
190
|
+
const recordId = validateRecordId(fields.get("recordId"));
|
|
191
|
+
const profile = validateProfile(fields.get("profile"), limits);
|
|
192
|
+
const algorithm = validateAlgorithmId(fields.get("algorithm"));
|
|
193
|
+
const normalizedByteLength = validateNonNegativeSafeInteger(fields.get("normalizedByteLength"));
|
|
194
|
+
if (!protocol.ok ||
|
|
195
|
+
!contextId.ok ||
|
|
196
|
+
!recordId.ok ||
|
|
197
|
+
!profile.ok ||
|
|
198
|
+
!algorithm.ok ||
|
|
199
|
+
normalizedByteLength === undefined)
|
|
200
|
+
return evidenceFailure("EVIDENCE_INVALID", limits);
|
|
201
|
+
const contentDigest = validateDigest(fields.get("contentDigest"), algorithm.value);
|
|
202
|
+
const recordDigest = validateDigest(fields.get("recordDigest"), algorithm.value);
|
|
203
|
+
if (!contentDigest.ok || !recordDigest.ok)
|
|
204
|
+
return evidenceFailure("EVIDENCE_INVALID", limits);
|
|
205
|
+
return success(Object.freeze({
|
|
206
|
+
protocolVersion: 1,
|
|
207
|
+
contextId: contextId.value.value,
|
|
208
|
+
recordId: recordId.value.value,
|
|
209
|
+
profile: profile.value,
|
|
210
|
+
algorithm: algorithm.value,
|
|
211
|
+
normalizedByteLength,
|
|
212
|
+
contentDigest: contentDigest.value.toHex(),
|
|
213
|
+
recordDigest: recordDigest.value.toHex(),
|
|
214
|
+
}));
|
|
215
|
+
}
|
|
216
|
+
function parsePrevious(value, algorithm, limits) {
|
|
217
|
+
const fields = strictFields(value, ["kind", "value"], true);
|
|
218
|
+
if (fields === undefined)
|
|
219
|
+
return evidenceFailure("EVIDENCE_INVALID", limits);
|
|
220
|
+
if (fields.get("kind") === "none" && fields.size === 1)
|
|
221
|
+
return success(Object.freeze({ kind: "none" }));
|
|
222
|
+
if (fields.get("kind") !== "digest" || fields.size !== 2)
|
|
223
|
+
return evidenceFailure("EVIDENCE_INVALID", limits);
|
|
224
|
+
const digest = validateDigest(fields.get("value"), algorithm);
|
|
225
|
+
if (!digest.ok)
|
|
226
|
+
return evidenceFailure("EVIDENCE_INVALID", limits);
|
|
227
|
+
return success(Object.freeze({ kind: "digest", value: digest.value.toHex() }));
|
|
228
|
+
}
|
|
229
|
+
function parseBoundaries(value) {
|
|
230
|
+
const fields = strictFields(value, ["start", "end"]);
|
|
231
|
+
if (fields === undefined)
|
|
232
|
+
return undefined;
|
|
233
|
+
const start = fields.get("start");
|
|
234
|
+
const end = fields.get("end");
|
|
235
|
+
if (!isBoundary(start) || !isBoundary(end))
|
|
236
|
+
return undefined;
|
|
237
|
+
return Object.freeze({ start, end });
|
|
238
|
+
}
|
|
239
|
+
function parseDiagnosticSummary(value) {
|
|
240
|
+
const fields = strictFields(value, ["errors", "warnings", "info", "truncated"]);
|
|
241
|
+
if (fields === undefined)
|
|
242
|
+
return undefined;
|
|
243
|
+
const errors = validateNonNegativeSafeInteger(fields.get("errors"));
|
|
244
|
+
const warnings = validateNonNegativeSafeInteger(fields.get("warnings"));
|
|
245
|
+
const info = validateNonNegativeSafeInteger(fields.get("info"));
|
|
246
|
+
const truncated = fields.get("truncated");
|
|
247
|
+
if (errors === undefined ||
|
|
248
|
+
warnings === undefined ||
|
|
249
|
+
info === undefined ||
|
|
250
|
+
typeof truncated !== "boolean")
|
|
251
|
+
return undefined;
|
|
252
|
+
return Object.freeze({ errors, warnings, info, truncated });
|
|
253
|
+
}
|
|
254
|
+
function strictFields(value, keys, optional = false) {
|
|
255
|
+
const entries = inspectPlainObject(value);
|
|
256
|
+
if (entries === undefined)
|
|
257
|
+
return undefined;
|
|
258
|
+
const fields = new Map(entries);
|
|
259
|
+
for (const key of fields.keys())
|
|
260
|
+
if (!keys.includes(key))
|
|
261
|
+
return undefined;
|
|
262
|
+
if (!optional && fields.size !== keys.length)
|
|
263
|
+
return undefined;
|
|
264
|
+
if (optional && fields.size > keys.length)
|
|
265
|
+
return undefined;
|
|
266
|
+
return fields;
|
|
267
|
+
}
|
|
268
|
+
function validateNonNegativeSafeInteger(value) {
|
|
269
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : undefined;
|
|
270
|
+
}
|
|
271
|
+
function isBoundary(value) {
|
|
272
|
+
return value === "verified" || value === "unverified" || value === "not-applicable";
|
|
273
|
+
}
|
|
274
|
+
function isStatus(value) {
|
|
275
|
+
return (value === "valid" || value === "invalid" || value === "indeterminate" || value === "aborted");
|
|
276
|
+
}
|
|
277
|
+
function evidenceFailure(code, limits) {
|
|
278
|
+
const collector = new DiagnosticCollector(limits);
|
|
279
|
+
collector.addCode(code, "input");
|
|
280
|
+
return failure(collector.finish());
|
|
281
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { digestBytesForTrustedFrame } from "../domain/digest.js";
|
|
3
|
+
import { encodeFrame, encodeTrustedFrame } from "./frame-encoder.js";
|
|
4
|
+
export function buildContentFrame(input, limits) {
|
|
5
|
+
const frame = {
|
|
6
|
+
kind: "content",
|
|
7
|
+
fields: [
|
|
8
|
+
{ tag: 1, type: "utf8", value: input.algorithm },
|
|
9
|
+
{ tag: 2, type: "utf8", value: input.profileId },
|
|
10
|
+
{ tag: 3, type: "utf8", value: input.profileVersion },
|
|
11
|
+
{ tag: 4, type: "bytes", value: input.normalizedBytes },
|
|
12
|
+
],
|
|
13
|
+
};
|
|
14
|
+
return encodeFrame(frame, limits);
|
|
15
|
+
}
|
|
16
|
+
export function buildRecordFrame(input, limits) {
|
|
17
|
+
const frame = {
|
|
18
|
+
kind: "record",
|
|
19
|
+
fields: [
|
|
20
|
+
{ tag: 1, type: "utf8", value: input.algorithm },
|
|
21
|
+
{ tag: 2, type: "utf8", value: input.contextId },
|
|
22
|
+
{ tag: 3, type: "utf8", value: input.recordId },
|
|
23
|
+
{ tag: 4, type: "utf8", value: input.profileId },
|
|
24
|
+
{ tag: 5, type: "utf8", value: input.profileVersion },
|
|
25
|
+
{ tag: 6, type: "uint64", value: input.normalizedByteLength },
|
|
26
|
+
{ tag: 7, type: "bytes", value: input.contentDigest.toBytes() },
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
return encodeFrame(frame, limits);
|
|
30
|
+
}
|
|
31
|
+
export function buildLinkFrame(input, limits) {
|
|
32
|
+
const previous = input.previousLinkDigest;
|
|
33
|
+
const frame = {
|
|
34
|
+
kind: "link",
|
|
35
|
+
fields: [
|
|
36
|
+
{ tag: 1, type: "utf8", value: input.algorithm },
|
|
37
|
+
{ tag: 2, type: "utf8", value: input.contextId },
|
|
38
|
+
{ tag: 3, type: "utf8", value: input.sequenceId },
|
|
39
|
+
{ tag: 4, type: "uint64", value: input.position },
|
|
40
|
+
{ tag: 5, type: "utf8", value: input.recordId },
|
|
41
|
+
{ tag: 6, type: "bytes", value: input.recordDigest.toBytes() },
|
|
42
|
+
previous === undefined
|
|
43
|
+
? { tag: 7, type: "none" }
|
|
44
|
+
: { tag: 7, type: "bytes", value: previous.toBytes() },
|
|
45
|
+
],
|
|
46
|
+
};
|
|
47
|
+
return encodeFrame(frame, limits);
|
|
48
|
+
}
|
|
49
|
+
export function buildEvidenceFrame(input, limits) {
|
|
50
|
+
const frame = {
|
|
51
|
+
kind: "evidence",
|
|
52
|
+
fields: [
|
|
53
|
+
{ tag: 1, type: "utf8", value: input.algorithm },
|
|
54
|
+
{ tag: 2, type: "utf8", value: input.schemaUrn },
|
|
55
|
+
{ tag: 3, type: "bytes", value: input.evidenceJcsBytes },
|
|
56
|
+
],
|
|
57
|
+
};
|
|
58
|
+
return encodeFrame(frame, limits);
|
|
59
|
+
}
|
|
60
|
+
export function buildTrustedContentFrame(input, limits) {
|
|
61
|
+
return encodeTrustedFrame({
|
|
62
|
+
kind: "content",
|
|
63
|
+
fields: [
|
|
64
|
+
{ tag: 1, type: "utf8", value: input.algorithm },
|
|
65
|
+
{ tag: 2, type: "utf8", value: input.profileId },
|
|
66
|
+
{ tag: 3, type: "utf8", value: input.profileVersion },
|
|
67
|
+
{ tag: 4, type: "bytes", value: input.normalizedBytes },
|
|
68
|
+
],
|
|
69
|
+
}, limits);
|
|
70
|
+
}
|
|
71
|
+
export function buildTrustedRecordFrame(input, limits) {
|
|
72
|
+
return encodeTrustedFrame({
|
|
73
|
+
kind: "record",
|
|
74
|
+
fields: [
|
|
75
|
+
{ tag: 1, type: "utf8", value: input.algorithm },
|
|
76
|
+
{ tag: 2, type: "utf8", value: input.contextId },
|
|
77
|
+
{ tag: 3, type: "utf8", value: input.recordId },
|
|
78
|
+
{ tag: 4, type: "utf8", value: input.profileId },
|
|
79
|
+
{ tag: 5, type: "utf8", value: input.profileVersion },
|
|
80
|
+
{ tag: 6, type: "uint64", value: input.normalizedByteLength },
|
|
81
|
+
{ tag: 7, type: "bytes", value: digestBytesForTrustedFrame(input.contentDigest) },
|
|
82
|
+
],
|
|
83
|
+
}, limits);
|
|
84
|
+
}
|
|
85
|
+
export function buildTrustedLinkFrame(input, limits) {
|
|
86
|
+
return encodeTrustedFrame({
|
|
87
|
+
kind: "link",
|
|
88
|
+
fields: [
|
|
89
|
+
{ tag: 1, type: "utf8", value: input.algorithm },
|
|
90
|
+
{ tag: 2, type: "utf8", value: input.contextId },
|
|
91
|
+
{ tag: 3, type: "utf8", value: input.sequenceId },
|
|
92
|
+
{ tag: 4, type: "uint64", value: input.position },
|
|
93
|
+
{ tag: 5, type: "utf8", value: input.recordId },
|
|
94
|
+
{ tag: 6, type: "bytes", value: digestBytesForTrustedFrame(input.recordDigest) },
|
|
95
|
+
input.previousLinkDigest === undefined
|
|
96
|
+
? { tag: 7, type: "none" }
|
|
97
|
+
: {
|
|
98
|
+
tag: 7,
|
|
99
|
+
type: "bytes",
|
|
100
|
+
value: digestBytesForTrustedFrame(input.previousLinkDigest),
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
}, limits);
|
|
104
|
+
}
|
|
105
|
+
export function buildTrustedEvidenceFrame(input, limits) {
|
|
106
|
+
return encodeTrustedFrame({
|
|
107
|
+
kind: "evidence",
|
|
108
|
+
fields: [
|
|
109
|
+
{ tag: 1, type: "utf8", value: input.algorithm },
|
|
110
|
+
{ tag: 2, type: "utf8", value: input.schemaUrn },
|
|
111
|
+
{ tag: 3, type: "bytes", value: input.evidenceJcsBytes },
|
|
112
|
+
],
|
|
113
|
+
}, limits);
|
|
114
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { types } from "node:util";
|
|
3
|
+
import { failure, success } from "../domain/operation-result.js";
|
|
4
|
+
import { DiagnosticCollector } from "../validation/diagnostic-collector.js";
|
|
5
|
+
import { encodeUtf8 } from "../validation/utf8-validation.js";
|
|
6
|
+
import { inspectPlainObject, isPlainObject } from "../validation/object-inspection.js";
|
|
7
|
+
import { ByteArraySink } from "../normalization/byte-sink.js";
|
|
8
|
+
const MAGIC = "NOEOSVE1";
|
|
9
|
+
const PROTOCOL_VERSION = 1;
|
|
10
|
+
const KIND_CODES = Object.freeze({
|
|
11
|
+
content: 0x01,
|
|
12
|
+
record: 0x02,
|
|
13
|
+
link: 0x03,
|
|
14
|
+
evidence: 0x04,
|
|
15
|
+
});
|
|
16
|
+
const MAGIC_BYTES = new TextEncoder().encode(MAGIC);
|
|
17
|
+
const UTF8_ENCODER = new TextEncoder();
|
|
18
|
+
const SHA256_BYTES = UTF8_ENCODER.encode("sha-256");
|
|
19
|
+
const SHA384_BYTES = UTF8_ENCODER.encode("sha-384");
|
|
20
|
+
const SHA512_BYTES = UTF8_ENCODER.encode("sha-512");
|
|
21
|
+
const RAW_PROFILE_BYTES = UTF8_ENCODER.encode("dev.noeos.raw-bytes");
|
|
22
|
+
const JCS_PROFILE_BYTES = UTF8_ENCODER.encode("dev.noeos.jcs");
|
|
23
|
+
const PROFILE_VERSION_BYTES = UTF8_ENCODER.encode("1.0.0");
|
|
24
|
+
export function encodeFrame(input, limits) {
|
|
25
|
+
const frameInput = validateFrameInput(input);
|
|
26
|
+
if (!frameInput.ok)
|
|
27
|
+
return frameFailure(frameInput.code, limits);
|
|
28
|
+
const kindCode = KIND_CODES[frameInput.value.kind];
|
|
29
|
+
if (frameInput.value.fields.length > 0xffff)
|
|
30
|
+
return frameFailure("FRAME_LENGTH_INVALID", limits);
|
|
31
|
+
const encodedFields = [];
|
|
32
|
+
let previousTag = 0;
|
|
33
|
+
for (const field of frameInput.value.fields) {
|
|
34
|
+
if (!Number.isSafeInteger(field.tag) || field.tag < 1 || field.tag > 0xffff) {
|
|
35
|
+
return frameFailure("FRAME_LENGTH_INVALID", limits);
|
|
36
|
+
}
|
|
37
|
+
if (field.tag === previousTag)
|
|
38
|
+
return frameFailure("FRAME_FIELD_DUPLICATE", limits);
|
|
39
|
+
if (field.tag < previousTag)
|
|
40
|
+
return frameFailure("FRAME_FIELD_ORDER_INVALID", limits);
|
|
41
|
+
previousTag = field.tag;
|
|
42
|
+
const encoded = encodeField(field, limits);
|
|
43
|
+
if (!encoded.ok)
|
|
44
|
+
return encoded;
|
|
45
|
+
encodedFields.push(encoded.value);
|
|
46
|
+
}
|
|
47
|
+
const sink = new ByteArraySink(limits.maxPayloadBytes);
|
|
48
|
+
try {
|
|
49
|
+
sink.write(new TextEncoder().encode(MAGIC));
|
|
50
|
+
sink.write(Uint8Array.of(kindCode, 0, PROTOCOL_VERSION));
|
|
51
|
+
sink.write(uint16Bytes(encodedFields.length));
|
|
52
|
+
for (const field of encodedFields) {
|
|
53
|
+
sink.write(uint16Bytes(field.tag));
|
|
54
|
+
sink.write(Uint8Array.of(field.typeCode));
|
|
55
|
+
sink.write(uint64Bytes(field.value.length));
|
|
56
|
+
sink.write(field.value);
|
|
57
|
+
}
|
|
58
|
+
return { ok: true, value: sink.toBytes(), diagnostics: Object.freeze([]) };
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return frameFailure("FRAME_LENGTH_INVALID", limits);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/** Internal fast path. Callers must have completed positive validation. */
|
|
65
|
+
export function encodeTrustedFrame(input, limits) {
|
|
66
|
+
const kindCode = KIND_CODES[input.kind];
|
|
67
|
+
const encodedFields = [];
|
|
68
|
+
let total = MAGIC_BYTES.length + 3 + 2;
|
|
69
|
+
try {
|
|
70
|
+
for (const field of input.fields) {
|
|
71
|
+
const encoded = encodeTrustedField(field, limits);
|
|
72
|
+
total += 2 + 1 + 8 + encoded.length;
|
|
73
|
+
encodedFields.push(encoded);
|
|
74
|
+
}
|
|
75
|
+
if (input.fields.length > 0xffff || total > limits.maxPayloadBytes) {
|
|
76
|
+
return frameFailure("FRAME_LENGTH_INVALID", limits);
|
|
77
|
+
}
|
|
78
|
+
const output = new Uint8Array(total);
|
|
79
|
+
let offset = 0;
|
|
80
|
+
output.set(MAGIC_BYTES, offset);
|
|
81
|
+
offset += MAGIC_BYTES.length;
|
|
82
|
+
output[offset++] = kindCode;
|
|
83
|
+
output[offset++] = 0;
|
|
84
|
+
output[offset++] = PROTOCOL_VERSION;
|
|
85
|
+
output[offset++] = (encodedFields.length >>> 8) & 0xff;
|
|
86
|
+
output[offset++] = encodedFields.length & 0xff;
|
|
87
|
+
for (const field of encodedFields) {
|
|
88
|
+
output[offset++] = (field.tag >>> 8) & 0xff;
|
|
89
|
+
output[offset++] = field.tag & 0xff;
|
|
90
|
+
output[offset++] = field.typeCode;
|
|
91
|
+
writeUint64(output, offset, field.length);
|
|
92
|
+
offset += 8;
|
|
93
|
+
if (field.value instanceof Uint8Array) {
|
|
94
|
+
output.set(field.value, offset);
|
|
95
|
+
offset += field.length;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
writeUint64(output, offset, field.value);
|
|
99
|
+
offset += 8;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return success(output);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return frameFailure("FRAME_LENGTH_INVALID", limits);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function validateFrameInput(input) {
|
|
109
|
+
if (!isPlainObject(input) || !isFrameKind(input["kind"]))
|
|
110
|
+
return { ok: false, code: "FRAME_KIND_UNKNOWN" };
|
|
111
|
+
if (!Array.isArray(input["fields"]) || types.isProxy(input["fields"]))
|
|
112
|
+
return { ok: false, code: "FRAME_LENGTH_INVALID" };
|
|
113
|
+
const fields = [];
|
|
114
|
+
for (const field of input["fields"]) {
|
|
115
|
+
const validated = validateFrameField(field);
|
|
116
|
+
if (validated === undefined)
|
|
117
|
+
return { ok: false, code: "FRAME_FIELD_TYPE_INVALID" };
|
|
118
|
+
fields.push(validated);
|
|
119
|
+
}
|
|
120
|
+
return { ok: true, value: { kind: input["kind"], fields } };
|
|
121
|
+
}
|
|
122
|
+
function validateFrameField(input) {
|
|
123
|
+
if (!isPlainObject(input))
|
|
124
|
+
return undefined;
|
|
125
|
+
const entries = inspectPlainObject(input);
|
|
126
|
+
if (entries === undefined)
|
|
127
|
+
return undefined;
|
|
128
|
+
const properties = new Map(entries);
|
|
129
|
+
const tag = properties.get("tag");
|
|
130
|
+
const type = properties.get("type");
|
|
131
|
+
if (typeof tag !== "number" || typeof type !== "string")
|
|
132
|
+
return undefined;
|
|
133
|
+
if (type === "bytes") {
|
|
134
|
+
const value = properties.get("value");
|
|
135
|
+
if (types.isProxy(value) || !(value instanceof Uint8Array))
|
|
136
|
+
return undefined;
|
|
137
|
+
return { tag, type, value };
|
|
138
|
+
}
|
|
139
|
+
if (type === "utf8") {
|
|
140
|
+
const value = properties.get("value");
|
|
141
|
+
if (typeof value !== "string")
|
|
142
|
+
return undefined;
|
|
143
|
+
return { tag, type, value };
|
|
144
|
+
}
|
|
145
|
+
if (type === "uint64") {
|
|
146
|
+
const value = properties.get("value");
|
|
147
|
+
if (typeof value !== "number")
|
|
148
|
+
return undefined;
|
|
149
|
+
return { tag, type, value };
|
|
150
|
+
}
|
|
151
|
+
if (type === "none" && !properties.has("value"))
|
|
152
|
+
return { tag, type };
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
function isFrameKind(value) {
|
|
156
|
+
return value === "content" || value === "record" || value === "link" || value === "evidence";
|
|
157
|
+
}
|
|
158
|
+
function encodeField(field, limits) {
|
|
159
|
+
if (field.type === "bytes") {
|
|
160
|
+
return successField(field.tag, 0x01, field.value);
|
|
161
|
+
}
|
|
162
|
+
if (field.type === "utf8") {
|
|
163
|
+
const encoded = encodeUtf8(field.value, limits.maxPayloadBytes);
|
|
164
|
+
if (!encoded.ok)
|
|
165
|
+
return encoded;
|
|
166
|
+
return successField(field.tag, 0x02, encoded.value);
|
|
167
|
+
}
|
|
168
|
+
if (field.type === "uint64") {
|
|
169
|
+
if (!Number.isSafeInteger(field.value) || field.value < 0)
|
|
170
|
+
return frameFailure("FRAME_LENGTH_INVALID", limits);
|
|
171
|
+
return successField(field.tag, 0x03, uint64Bytes(field.value));
|
|
172
|
+
}
|
|
173
|
+
return successField(field.tag, 0x04, new Uint8Array(0));
|
|
174
|
+
}
|
|
175
|
+
function encodeTrustedField(field, limits) {
|
|
176
|
+
if (field.type === "bytes") {
|
|
177
|
+
return { tag: field.tag, typeCode: 0x01, value: field.value, length: field.value.length };
|
|
178
|
+
}
|
|
179
|
+
if (field.type === "utf8") {
|
|
180
|
+
const value = trustedUtf8(field.value);
|
|
181
|
+
if (value.length > limits.maxPayloadBytes)
|
|
182
|
+
throw new RangeError("frame field too large");
|
|
183
|
+
return { tag: field.tag, typeCode: 0x02, value, length: value.length };
|
|
184
|
+
}
|
|
185
|
+
if (field.type === "uint64")
|
|
186
|
+
return { tag: field.tag, typeCode: 0x03, value: field.value, length: 8 };
|
|
187
|
+
return { tag: field.tag, typeCode: 0x04, value: 0, length: 0 };
|
|
188
|
+
}
|
|
189
|
+
function trustedUtf8(value) {
|
|
190
|
+
if (value === "sha-256")
|
|
191
|
+
return SHA256_BYTES;
|
|
192
|
+
if (value === "sha-384")
|
|
193
|
+
return SHA384_BYTES;
|
|
194
|
+
if (value === "sha-512")
|
|
195
|
+
return SHA512_BYTES;
|
|
196
|
+
if (value === "dev.noeos.raw-bytes")
|
|
197
|
+
return RAW_PROFILE_BYTES;
|
|
198
|
+
if (value === "dev.noeos.jcs")
|
|
199
|
+
return JCS_PROFILE_BYTES;
|
|
200
|
+
if (value === "1.0.0")
|
|
201
|
+
return PROFILE_VERSION_BYTES;
|
|
202
|
+
return UTF8_ENCODER.encode(value);
|
|
203
|
+
}
|
|
204
|
+
function successField(tag, typeCode, value) {
|
|
205
|
+
return {
|
|
206
|
+
ok: true,
|
|
207
|
+
value: Object.freeze({ tag, typeCode, value: Uint8Array.from(value) }),
|
|
208
|
+
diagnostics: Object.freeze([]),
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
function uint16Bytes(value) {
|
|
212
|
+
return Uint8Array.of((value >>> 8) & 0xff, value & 0xff);
|
|
213
|
+
}
|
|
214
|
+
function uint64Bytes(value) {
|
|
215
|
+
const output = new Uint8Array(8);
|
|
216
|
+
let remaining = BigInt(value);
|
|
217
|
+
for (let index = 7; index >= 0; index -= 1) {
|
|
218
|
+
output[index] = Number(remaining & 0xffn);
|
|
219
|
+
remaining >>= 8n;
|
|
220
|
+
}
|
|
221
|
+
return output;
|
|
222
|
+
}
|
|
223
|
+
function writeUint64(output, offset, value) {
|
|
224
|
+
let remaining = BigInt(value);
|
|
225
|
+
for (let index = offset + 7; index >= offset; index -= 1) {
|
|
226
|
+
output[index] = Number(remaining & 0xffn);
|
|
227
|
+
remaining >>= 8n;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
function frameFailure(code, limits) {
|
|
231
|
+
const collector = new DiagnosticCollector(limits);
|
|
232
|
+
collector.addCode(code, "input");
|
|
233
|
+
return failure(collector.finish());
|
|
234
|
+
}
|