space-data-module-sdk 0.5.14 → 0.5.18
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/README.md +91 -1
- package/package.json +8 -4
- package/schemas/HostStorageAbi.fbs +53 -0
- package/src/bundle/codec.js +1 -1
- package/src/compliance/pluginCompliance.js +0 -130
- package/src/generated/orbpro/invoke/plugin-invoke-request.js +1 -1
- package/src/generated/orbpro/invoke/plugin-invoke-response.js +1 -1
- package/src/generated/orbpro/manifest/accepted-type-set.js +1 -1
- package/src/generated/orbpro/manifest/build-artifact.js +1 -1
- package/src/generated/orbpro/manifest/host-capability.js +1 -1
- package/src/generated/orbpro/manifest/method-manifest.js +1 -1
- package/src/generated/orbpro/manifest/plugin-manifest.js +1 -1
- package/src/generated/orbpro/manifest/port-manifest.js +1 -1
- package/src/generated/orbpro/manifest/protocol-spec.js +1 -1
- package/src/generated/orbpro/manifest/timer-spec.js +1 -1
- package/src/generated/orbpro/module/canonicalization-rule.js +1 -1
- package/src/generated/orbpro/module/module-bundle-entry.js +1 -1
- package/src/generated/orbpro/module/module-bundle.js +1 -1
- package/src/generated/orbpro/stream/flat-buffer-type-ref.js +1 -1
- package/src/generated/orbpro/stream/typed-arena-buffer.js +1 -1
- package/src/index.d.ts +157 -1
- package/src/index.js +1 -0
- package/src/invoke/codec.js +10 -8
- package/src/manifest/codec.js +1 -1
- package/src/runtime-host/flatsqlRuntimeStore.js +217 -0
- package/src/runtime-host/index.js +21 -0
- package/src/runtime-host/moduleRegistry.js +92 -0
- package/src/runtime-host/runtimeRegionStore.js +245 -0
- package/src/testing/buildWasmEdgeRunner.js +253 -0
- package/src/testing/index.d.ts +311 -0
- package/src/testing/index.js +21 -0
- package/src/testing/moduleHarness.js +163 -0
- package/src/testing/native/wasmedge_emscripten_pthread_runner.c +3111 -0
- package/src/testing/processInvoke.js +467 -0
- package/src/testing/publicationProtectionDemo.js +271 -0
- package/src/testing/streamInvokeCodec.js +175 -0
- package/src/transport/records.js +56 -55
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import * as flatbuffers from "flatbuffers";
|
|
2
|
+
|
|
3
|
+
import { createRecipientKeypairHex, protectModuleArtifact } from "../compiler/compileModule.js";
|
|
4
|
+
import { extractPublicationRecordCollection } from "../transport/records.js";
|
|
5
|
+
import { REC } from "spacedatastandards.org/lib/js/REC/REC.js";
|
|
6
|
+
import { Record } from "spacedatastandards.org/lib/js/REC/Record.js";
|
|
7
|
+
import { PNM } from "spacedatastandards.org/lib/js/PNM/main.js";
|
|
8
|
+
import { ENC } from "spacedatastandards.org/lib/js/ENC/main.js";
|
|
9
|
+
|
|
10
|
+
const MINIMAL_WASM_BYTES = Uint8Array.of(
|
|
11
|
+
0x00,
|
|
12
|
+
0x61,
|
|
13
|
+
0x73,
|
|
14
|
+
0x6d,
|
|
15
|
+
0x01,
|
|
16
|
+
0x00,
|
|
17
|
+
0x00,
|
|
18
|
+
0x00,
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export function createPublicationProtectionDemoManifest() {
|
|
22
|
+
return {
|
|
23
|
+
pluginId: "com.digitalarsenal.examples.publication-protection-demo",
|
|
24
|
+
name: "Publication Protection Demo",
|
|
25
|
+
version: "0.1.0",
|
|
26
|
+
pluginFamily: "propagator",
|
|
27
|
+
capabilities: ["clock", "crypto_sign", "crypto_encrypt"],
|
|
28
|
+
externalInterfaces: [],
|
|
29
|
+
methods: [
|
|
30
|
+
{
|
|
31
|
+
methodId: "propagate",
|
|
32
|
+
displayName: "Propagate",
|
|
33
|
+
inputPorts: [
|
|
34
|
+
{
|
|
35
|
+
portId: "request",
|
|
36
|
+
acceptedTypeSets: [
|
|
37
|
+
{
|
|
38
|
+
setId: "omm-request",
|
|
39
|
+
allowedTypes: [
|
|
40
|
+
{
|
|
41
|
+
schemaName: "OMM.fbs",
|
|
42
|
+
fileIdentifier: "$OMM",
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
minStreams: 1,
|
|
48
|
+
maxStreams: 1,
|
|
49
|
+
required: true,
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
outputPorts: [
|
|
53
|
+
{
|
|
54
|
+
portId: "state",
|
|
55
|
+
acceptedTypeSets: [
|
|
56
|
+
{
|
|
57
|
+
setId: "state-vector",
|
|
58
|
+
allowedTypes: [
|
|
59
|
+
{
|
|
60
|
+
schemaName: "StateVector.fbs",
|
|
61
|
+
fileIdentifier: "STVC",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
schemaName: "StateVector.fbs",
|
|
65
|
+
fileIdentifier: "STVC",
|
|
66
|
+
wireFormat: "aligned-binary",
|
|
67
|
+
rootTypeName: "StateVector",
|
|
68
|
+
byteLength: 72,
|
|
69
|
+
requiredAlignment: 8,
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
minStreams: 1,
|
|
75
|
+
maxStreams: 1,
|
|
76
|
+
required: true,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
maxBatch: 32,
|
|
80
|
+
drainPolicy: "drain-to-empty",
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
schemasUsed: [
|
|
84
|
+
{
|
|
85
|
+
schemaName: "OMM.fbs",
|
|
86
|
+
fileIdentifier: "$OMM",
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
schemaName: "StateVector.fbs",
|
|
90
|
+
fileIdentifier: "STVC",
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
schemaName: "StateVector.fbs",
|
|
94
|
+
fileIdentifier: "STVC",
|
|
95
|
+
wireFormat: "aligned-binary",
|
|
96
|
+
rootTypeName: "StateVector",
|
|
97
|
+
byteLength: 72,
|
|
98
|
+
requiredAlignment: 8,
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function summarizeAlignedBinaryContract(manifest = {}) {
|
|
105
|
+
const summaries = [];
|
|
106
|
+
for (const method of Array.isArray(manifest.methods) ? manifest.methods : []) {
|
|
107
|
+
const ports = [
|
|
108
|
+
...(Array.isArray(method.inputPorts) ? method.inputPorts : []),
|
|
109
|
+
...(Array.isArray(method.outputPorts) ? method.outputPorts : []),
|
|
110
|
+
];
|
|
111
|
+
for (const port of ports) {
|
|
112
|
+
for (const typeSet of Array.isArray(port.acceptedTypeSets)
|
|
113
|
+
? port.acceptedTypeSets
|
|
114
|
+
: []) {
|
|
115
|
+
const allowedTypes = Array.isArray(typeSet.allowedTypes)
|
|
116
|
+
? typeSet.allowedTypes
|
|
117
|
+
: [];
|
|
118
|
+
for (const allowedType of allowedTypes) {
|
|
119
|
+
if (allowedType?.wireFormat !== "aligned-binary") {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
const hasFlatbufferFallback = allowedTypes.some(
|
|
123
|
+
(candidate) =>
|
|
124
|
+
(candidate?.wireFormat ?? "flatbuffer") === "flatbuffer" &&
|
|
125
|
+
candidate?.schemaName === allowedType.schemaName &&
|
|
126
|
+
candidate?.fileIdentifier === allowedType.fileIdentifier,
|
|
127
|
+
);
|
|
128
|
+
summaries.push({
|
|
129
|
+
methodId: method.methodId ?? null,
|
|
130
|
+
portId: port.portId ?? null,
|
|
131
|
+
setId: typeSet.setId ?? null,
|
|
132
|
+
schemaName: allowedType.schemaName ?? null,
|
|
133
|
+
fileIdentifier: allowedType.fileIdentifier ?? null,
|
|
134
|
+
rootTypeName: allowedType.rootTypeName ?? null,
|
|
135
|
+
byteLength: allowedType.byteLength ?? null,
|
|
136
|
+
requiredAlignment: allowedType.requiredAlignment ?? null,
|
|
137
|
+
hasFlatbufferFallback,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return summaries;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function parseStandardsRec(recordCollectionBytes) {
|
|
147
|
+
const recBuffer = new flatbuffers.ByteBuffer(recordCollectionBytes);
|
|
148
|
+
const rec = REC.getRootAsREC(recBuffer);
|
|
149
|
+
const records = [];
|
|
150
|
+
for (let index = 0; index < rec.recordsLength(); index += 1) {
|
|
151
|
+
const record = rec.RECORDS(index, new Record());
|
|
152
|
+
if (!record) {
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
const standard = record.standard() ?? null;
|
|
156
|
+
if (standard === "PNM") {
|
|
157
|
+
const pnm = record.value(new PNM());
|
|
158
|
+
records.push({
|
|
159
|
+
standard,
|
|
160
|
+
fileIdentifier: "$PNM",
|
|
161
|
+
fileName: pnm?.FILE_NAME() ?? null,
|
|
162
|
+
fileId: pnm?.FILE_ID() ?? null,
|
|
163
|
+
cid: pnm?.CID() ?? null,
|
|
164
|
+
hasSignature: Boolean(pnm?.SIGNATURE()),
|
|
165
|
+
});
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (standard === "ENC") {
|
|
169
|
+
const enc = record.value(new ENC());
|
|
170
|
+
records.push({
|
|
171
|
+
standard,
|
|
172
|
+
fileIdentifier: "$ENC",
|
|
173
|
+
context: enc?.CONTEXT() ?? null,
|
|
174
|
+
rootType: enc?.ROOT_TYPE() ?? null,
|
|
175
|
+
nonceLength: enc?.nonceStartLength() ?? 0,
|
|
176
|
+
ephemeralPublicKeyLength: enc?.ephemeralPublicKeyLength() ?? 0,
|
|
177
|
+
});
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
records.push({
|
|
181
|
+
standard,
|
|
182
|
+
fileIdentifier: null,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
fileIdentifier: "$REC",
|
|
187
|
+
version: rec.version() ?? null,
|
|
188
|
+
recordCount: records.length,
|
|
189
|
+
recordStandards: records.map((record) => record.standard),
|
|
190
|
+
usesStandardsFlatbuffers: REC.bufferHasIdentifier(
|
|
191
|
+
new flatbuffers.ByteBuffer(recordCollectionBytes),
|
|
192
|
+
),
|
|
193
|
+
records,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function summarizeProtectedArtifact(protectedArtifact) {
|
|
198
|
+
const parsed = extractPublicationRecordCollection(
|
|
199
|
+
protectedArtifact.protectedArtifactBytes,
|
|
200
|
+
);
|
|
201
|
+
if (!parsed) {
|
|
202
|
+
throw new Error("Protected artifact is missing the REC publication trailer.");
|
|
203
|
+
}
|
|
204
|
+
const trailer = parseStandardsRec(parsed.recordCollectionBytes);
|
|
205
|
+
return {
|
|
206
|
+
artifactId: protectedArtifact.payload.artifactId,
|
|
207
|
+
encrypted: protectedArtifact.encrypted,
|
|
208
|
+
trailer,
|
|
209
|
+
recordStandards: trailer.recordStandards,
|
|
210
|
+
pnm: parsed.pnm
|
|
211
|
+
? {
|
|
212
|
+
fileName: parsed.pnm.fileName ?? null,
|
|
213
|
+
fileId: parsed.pnm.fileId ?? null,
|
|
214
|
+
cid: parsed.pnm.cid ?? null,
|
|
215
|
+
hasSignature: Boolean(parsed.pnm.signature),
|
|
216
|
+
signatureType: parsed.pnm.signatureType ?? null,
|
|
217
|
+
publishTimestamp: parsed.pnm.publishTimestamp ?? null,
|
|
218
|
+
}
|
|
219
|
+
: null,
|
|
220
|
+
enc: parsed.enc
|
|
221
|
+
? {
|
|
222
|
+
context: parsed.enc.context ?? null,
|
|
223
|
+
rootType: parsed.enc.rootType ?? null,
|
|
224
|
+
keyExchange: parsed.enc.keyExchange ?? null,
|
|
225
|
+
symmetric: parsed.enc.symmetric ?? null,
|
|
226
|
+
keyDerivation: parsed.enc.keyDerivation ?? null,
|
|
227
|
+
nonceLength: parsed.enc.nonceStart?.length ?? 0,
|
|
228
|
+
ephemeralPublicKeyLength: parsed.enc.ephemeralPublicKey?.length ?? 0,
|
|
229
|
+
}
|
|
230
|
+
: null,
|
|
231
|
+
envelope: protectedArtifact.encryptedEnvelope
|
|
232
|
+
? {
|
|
233
|
+
scheme: protectedArtifact.encryptedEnvelope.scheme ?? null,
|
|
234
|
+
hasEncRecord: Boolean(
|
|
235
|
+
protectedArtifact.encryptedEnvelope.encRecordBase64,
|
|
236
|
+
),
|
|
237
|
+
hasPnmRecord: Boolean(
|
|
238
|
+
protectedArtifact.encryptedEnvelope.pnmRecordBase64,
|
|
239
|
+
),
|
|
240
|
+
}
|
|
241
|
+
: null,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export async function createPublicationProtectionDemoSummary(options = {}) {
|
|
246
|
+
const manifest = options.manifest ?? createPublicationProtectionDemoManifest();
|
|
247
|
+
const wasmBytes =
|
|
248
|
+
options.wasmBytes instanceof Uint8Array
|
|
249
|
+
? options.wasmBytes
|
|
250
|
+
: MINIMAL_WASM_BYTES;
|
|
251
|
+
const recipient = options.recipient ?? (await createRecipientKeypairHex());
|
|
252
|
+
const signedOnly = await protectModuleArtifact({
|
|
253
|
+
manifest,
|
|
254
|
+
wasmBytes,
|
|
255
|
+
mnemonic: options.mnemonic ?? null,
|
|
256
|
+
});
|
|
257
|
+
const encryptedDelivery = await protectModuleArtifact({
|
|
258
|
+
manifest,
|
|
259
|
+
wasmBytes,
|
|
260
|
+
mnemonic: options.mnemonic ?? null,
|
|
261
|
+
recipientPublicKeyHex: recipient.publicKeyHex,
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
return {
|
|
265
|
+
manifest,
|
|
266
|
+
recTrailer: parseStandardsRec(signedOnly.publicationRecordsBytes),
|
|
267
|
+
alignedBinaryContract: summarizeAlignedBinaryContract(manifest),
|
|
268
|
+
signedOnly: summarizeProtectedArtifact(signedOnly),
|
|
269
|
+
encryptedDelivery: summarizeProtectedArtifact(encryptedDelivery),
|
|
270
|
+
};
|
|
271
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import * as flatbuffers from "flatbuffers/mjs/flatbuffers.js";
|
|
2
|
+
|
|
3
|
+
import { DrainPolicy } from "../generated/orbpro/manifest/drain-policy.js";
|
|
4
|
+
import { TypedArenaBuffer } from "../generated/orbpro/stream/typed-arena-buffer.js";
|
|
5
|
+
|
|
6
|
+
function toByteBuffer(data) {
|
|
7
|
+
if (data instanceof flatbuffers.ByteBuffer) {
|
|
8
|
+
return data;
|
|
9
|
+
}
|
|
10
|
+
return new flatbuffers.ByteBuffer(data);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
class StreamInvokeRequest {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.bb = null;
|
|
16
|
+
this.bb_pos = 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
__init(i, bb) {
|
|
20
|
+
this.bb_pos = i;
|
|
21
|
+
this.bb = bb;
|
|
22
|
+
return this;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static getRootAsStreamInvokeRequest(bb, obj) {
|
|
26
|
+
return (obj || new StreamInvokeRequest()).__init(
|
|
27
|
+
bb.readInt32(bb.position()) + bb.position(),
|
|
28
|
+
bb,
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static startStreamInvokeRequest(builder) {
|
|
33
|
+
builder.startObject(4);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static addMethodId(builder, methodIdOffset) {
|
|
37
|
+
builder.addFieldOffset(0, methodIdOffset, 0);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static addInputs(builder, inputsOffset) {
|
|
41
|
+
builder.addFieldOffset(1, inputsOffset, 0);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
static createInputsVector(builder, data) {
|
|
45
|
+
builder.startVector(4, data.length, 4);
|
|
46
|
+
for (let i = data.length - 1; i >= 0; i -= 1) {
|
|
47
|
+
builder.addOffset(data[i]);
|
|
48
|
+
}
|
|
49
|
+
return builder.endVector();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static addOutputStreamCap(builder, outputStreamCap) {
|
|
53
|
+
builder.addFieldInt32(2, outputStreamCap, 0);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static addDrainPolicy(builder, drainPolicy) {
|
|
57
|
+
builder.addFieldInt8(3, drainPolicy, DrainPolicy.DRAIN_UNTIL_YIELD);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
static endStreamInvokeRequest(builder) {
|
|
61
|
+
const offset = builder.endObject();
|
|
62
|
+
builder.requiredField(offset, 4);
|
|
63
|
+
return offset;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
class StreamInvokeRequestT {
|
|
68
|
+
constructor(
|
|
69
|
+
methodId = null,
|
|
70
|
+
inputs = [],
|
|
71
|
+
outputStreamCap = 0,
|
|
72
|
+
drainPolicy = DrainPolicy.DRAIN_UNTIL_YIELD,
|
|
73
|
+
) {
|
|
74
|
+
this.methodId = methodId;
|
|
75
|
+
this.inputs = inputs;
|
|
76
|
+
this.outputStreamCap = outputStreamCap;
|
|
77
|
+
this.drainPolicy = drainPolicy;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
pack(builder) {
|
|
81
|
+
const methodId =
|
|
82
|
+
this.methodId !== null ? builder.createString(this.methodId) : 0;
|
|
83
|
+
const inputs = StreamInvokeRequest.createInputsVector(
|
|
84
|
+
builder,
|
|
85
|
+
builder.createObjectOffsetList(this.inputs),
|
|
86
|
+
);
|
|
87
|
+
StreamInvokeRequest.startStreamInvokeRequest(builder);
|
|
88
|
+
StreamInvokeRequest.addMethodId(builder, methodId);
|
|
89
|
+
StreamInvokeRequest.addInputs(builder, inputs);
|
|
90
|
+
StreamInvokeRequest.addOutputStreamCap(builder, this.outputStreamCap);
|
|
91
|
+
StreamInvokeRequest.addDrainPolicy(builder, this.drainPolicy);
|
|
92
|
+
return StreamInvokeRequest.endStreamInvokeRequest(builder);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
class StreamInvokeResponse {
|
|
97
|
+
constructor() {
|
|
98
|
+
this.bb = null;
|
|
99
|
+
this.bb_pos = 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
__init(i, bb) {
|
|
103
|
+
this.bb_pos = i;
|
|
104
|
+
this.bb = bb;
|
|
105
|
+
return this;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
static getRootAsStreamInvokeResponse(bb, obj) {
|
|
109
|
+
return (obj || new StreamInvokeResponse()).__init(
|
|
110
|
+
bb.readInt32(bb.position()) + bb.position(),
|
|
111
|
+
bb,
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
outputs(index, obj) {
|
|
116
|
+
const offset = this.bb.__offset(this.bb_pos, 4);
|
|
117
|
+
return offset
|
|
118
|
+
? (obj || new TypedArenaBuffer()).__init(
|
|
119
|
+
this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4),
|
|
120
|
+
this.bb,
|
|
121
|
+
)
|
|
122
|
+
: null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
outputsLength() {
|
|
126
|
+
const offset = this.bb.__offset(this.bb_pos, 4);
|
|
127
|
+
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
backlogRemaining() {
|
|
131
|
+
const offset = this.bb.__offset(this.bb_pos, 6);
|
|
132
|
+
return offset ? this.bb.readUint32(this.bb_pos + offset) : 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
yielded() {
|
|
136
|
+
const offset = this.bb.__offset(this.bb_pos, 8);
|
|
137
|
+
return offset ? !!this.bb.readInt8(this.bb_pos + offset) : false;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
errorCode() {
|
|
141
|
+
const offset = this.bb.__offset(this.bb_pos, 10);
|
|
142
|
+
return offset ? this.bb.readInt32(this.bb_pos + offset) : 0;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
errorMessage(optionalEncoding) {
|
|
146
|
+
const offset = this.bb.__offset(this.bb_pos, 12);
|
|
147
|
+
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
unpack() {
|
|
151
|
+
return {
|
|
152
|
+
outputs: this.bb.createObjList(this.outputs.bind(this), this.outputsLength()),
|
|
153
|
+
backlogRemaining: this.backlogRemaining(),
|
|
154
|
+
yielded: this.yielded(),
|
|
155
|
+
errorCode: this.errorCode(),
|
|
156
|
+
errorMessage: this.errorMessage(),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function encodeStreamInvokeRequest(request) {
|
|
162
|
+
const normalized =
|
|
163
|
+
request instanceof StreamInvokeRequestT
|
|
164
|
+
? request
|
|
165
|
+
: Object.assign(new StreamInvokeRequestT(), request);
|
|
166
|
+
const builder = new flatbuffers.Builder(1024);
|
|
167
|
+
builder.finish(normalized.pack(builder));
|
|
168
|
+
return builder.asUint8Array();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function decodeStreamInvokeResponse(data) {
|
|
172
|
+
return StreamInvokeResponse.getRootAsStreamInvokeResponse(
|
|
173
|
+
toByteBuffer(data),
|
|
174
|
+
).unpack();
|
|
175
|
+
}
|
package/src/transport/records.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import * as flatbuffers from "flatbuffers";
|
|
1
|
+
import * as flatbuffers from "flatbuffers/mjs/flatbuffers.js";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ENC,
|
|
5
|
+
ENCT,
|
|
6
|
+
KDF,
|
|
7
|
+
KeyExchange,
|
|
8
|
+
SymmetricAlgo,
|
|
9
|
+
} from "spacedatastandards.org/lib/js/ENC/main.js";
|
|
4
10
|
import { PNM, PNMT } from "spacedatastandards.org/lib/js/PNM/main.js";
|
|
5
11
|
import { REC, RECT } from "spacedatastandards.org/lib/js/REC/REC.js";
|
|
6
12
|
import { Record, RecordT } from "spacedatastandards.org/lib/js/REC/Record.js";
|
|
@@ -75,6 +81,16 @@ function readUint16LE(buffer, offset, label) {
|
|
|
75
81
|
return buffer[offset] | (buffer[offset + 1] << 8);
|
|
76
82
|
}
|
|
77
83
|
|
|
84
|
+
function getRecordValueType(recordTable) {
|
|
85
|
+
if (typeof recordTable.valueType === "function") {
|
|
86
|
+
return recordTable.valueType();
|
|
87
|
+
}
|
|
88
|
+
if (typeof recordTable.value_type === "function") {
|
|
89
|
+
return recordTable.value_type();
|
|
90
|
+
}
|
|
91
|
+
throw new TypeError("REC record table does not expose a value type accessor.");
|
|
92
|
+
}
|
|
93
|
+
|
|
78
94
|
function readUint32LE(buffer, offset, label) {
|
|
79
95
|
assertBounds(buffer, offset, 4, label);
|
|
80
96
|
return (
|
|
@@ -277,7 +293,27 @@ function validateEncTable(table, buffer, label) {
|
|
|
277
293
|
maxLength: 32,
|
|
278
294
|
});
|
|
279
295
|
assertOptionalStringField(buffer, tableMeta, 22, `${label} root type`);
|
|
280
|
-
const
|
|
296
|
+
const timestamp = table.TIMESTAMP();
|
|
297
|
+
const record = {
|
|
298
|
+
version: Number(table.VERSION()),
|
|
299
|
+
keyExchange:
|
|
300
|
+
KEY_EXCHANGE_NAME_BY_VALUE[table.KEY_EXCHANGE()] ??
|
|
301
|
+
String(table.KEY_EXCHANGE()),
|
|
302
|
+
symmetric:
|
|
303
|
+
SYMMETRIC_ALGO_NAME_BY_VALUE[table.SYMMETRIC()] ??
|
|
304
|
+
String(table.SYMMETRIC()),
|
|
305
|
+
keyDerivation:
|
|
306
|
+
KDF_NAME_BY_VALUE[table.KEY_DERIVATION()] ??
|
|
307
|
+
String(table.KEY_DERIVATION()),
|
|
308
|
+
ephemeralPublicKey: normalizeByteField(table.ephemeralPublicKeyArray()),
|
|
309
|
+
nonceStart: normalizeByteField(table.nonceStartArray()),
|
|
310
|
+
recipientKeyId: normalizeByteField(table.recipientKeyIdArray()),
|
|
311
|
+
context: normalizeStringField(table.CONTEXT()),
|
|
312
|
+
schemaHash: normalizeByteField(table.schemaHashArray()),
|
|
313
|
+
rootType: normalizeStringField(table.ROOT_TYPE()),
|
|
314
|
+
timestamp:
|
|
315
|
+
timestamp === undefined || timestamp === null ? 0 : Number(timestamp),
|
|
316
|
+
};
|
|
281
317
|
if (!record.ephemeralPublicKey?.length) {
|
|
282
318
|
throw new Error(`${label} is missing the ephemeral public key.`);
|
|
283
319
|
}
|
|
@@ -316,7 +352,17 @@ function validatePnmTable(table, buffer, label) {
|
|
|
316
352
|
assertOptionalStringField(buffer, tableMeta, 16, `${label} timestamp signature`);
|
|
317
353
|
assertOptionalStringField(buffer, tableMeta, 18, `${label} signature type`);
|
|
318
354
|
assertOptionalStringField(buffer, tableMeta, 20, `${label} timestamp signature type`);
|
|
319
|
-
const record =
|
|
355
|
+
const record = {
|
|
356
|
+
multiformatAddress: normalizeStringField(table.MULTIFORMAT_ADDRESS()),
|
|
357
|
+
publishTimestamp: normalizeStringField(table.PUBLISH_TIMESTAMP()),
|
|
358
|
+
cid: normalizeStringField(table.CID()),
|
|
359
|
+
fileName: normalizeStringField(table.FILE_NAME()),
|
|
360
|
+
fileId: normalizeStringField(table.FILE_ID()),
|
|
361
|
+
signature: normalizeStringField(table.SIGNATURE()),
|
|
362
|
+
timestampSignature: normalizeStringField(table.TIMESTAMP_SIGNATURE()),
|
|
363
|
+
signatureType: normalizeStringField(table.SIGNATURE_TYPE()),
|
|
364
|
+
timestampSignatureType: normalizeStringField(table.TIMESTAMP_SIGNATURE_TYPE()),
|
|
365
|
+
};
|
|
320
366
|
if (
|
|
321
367
|
!record.multiformatAddress &&
|
|
322
368
|
!record.publishTimestamp &&
|
|
@@ -426,48 +472,6 @@ function pnmTableFromObject(record = {}) {
|
|
|
426
472
|
);
|
|
427
473
|
}
|
|
428
474
|
|
|
429
|
-
function normalizeEncTable(table) {
|
|
430
|
-
if (!table) {
|
|
431
|
-
return null;
|
|
432
|
-
}
|
|
433
|
-
return {
|
|
434
|
-
version: Number(table.VERSION ?? 1),
|
|
435
|
-
keyExchange:
|
|
436
|
-
KEY_EXCHANGE_NAME_BY_VALUE[table.KEY_EXCHANGE] ?? String(table.KEY_EXCHANGE),
|
|
437
|
-
symmetric:
|
|
438
|
-
SYMMETRIC_ALGO_NAME_BY_VALUE[table.SYMMETRIC] ?? String(table.SYMMETRIC),
|
|
439
|
-
keyDerivation:
|
|
440
|
-
KDF_NAME_BY_VALUE[table.KEY_DERIVATION] ?? String(table.KEY_DERIVATION),
|
|
441
|
-
ephemeralPublicKey: normalizeByteField(table.EPHEMERAL_PUBLIC_KEY),
|
|
442
|
-
nonceStart: normalizeByteField(table.NONCE_START),
|
|
443
|
-
recipientKeyId: normalizeByteField(table.RECIPIENT_KEY_ID),
|
|
444
|
-
context: normalizeStringField(table.CONTEXT),
|
|
445
|
-
schemaHash: normalizeByteField(table.SCHEMA_HASH),
|
|
446
|
-
rootType: normalizeStringField(table.ROOT_TYPE),
|
|
447
|
-
timestamp:
|
|
448
|
-
table.TIMESTAMP === undefined || table.TIMESTAMP === null
|
|
449
|
-
? 0
|
|
450
|
-
: Number(table.TIMESTAMP),
|
|
451
|
-
};
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
function normalizePnmTable(table) {
|
|
455
|
-
if (!table) {
|
|
456
|
-
return null;
|
|
457
|
-
}
|
|
458
|
-
return {
|
|
459
|
-
multiformatAddress: normalizeStringField(table.MULTIFORMAT_ADDRESS),
|
|
460
|
-
publishTimestamp: normalizeStringField(table.PUBLISH_TIMESTAMP),
|
|
461
|
-
cid: normalizeStringField(table.CID),
|
|
462
|
-
fileName: normalizeStringField(table.FILE_NAME),
|
|
463
|
-
fileId: normalizeStringField(table.FILE_ID),
|
|
464
|
-
signature: normalizeStringField(table.SIGNATURE),
|
|
465
|
-
timestampSignature: normalizeStringField(table.TIMESTAMP_SIGNATURE),
|
|
466
|
-
signatureType: normalizeStringField(table.SIGNATURE_TYPE),
|
|
467
|
-
timestampSignatureType: normalizeStringField(table.TIMESTAMP_SIGNATURE_TYPE),
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
|
|
471
475
|
function readFooterLength(bytes) {
|
|
472
476
|
const view = toUint8Array(bytes);
|
|
473
477
|
if (view.length < TRAILER_FOOTER_LENGTH) {
|
|
@@ -601,7 +605,6 @@ export function decodePublicationRecordCollection(bytes) {
|
|
|
601
605
|
if (recordTables.length === 0) {
|
|
602
606
|
throw new Error("REC trailer does not contain any records.");
|
|
603
607
|
}
|
|
604
|
-
const collection = collectionTable.unpack();
|
|
605
608
|
const records = [];
|
|
606
609
|
let enc = null;
|
|
607
610
|
let pnm = null;
|
|
@@ -622,10 +625,9 @@ export function decodePublicationRecordCollection(bytes) {
|
|
|
622
625
|
8,
|
|
623
626
|
`REC trailer record ${index} standard`,
|
|
624
627
|
);
|
|
625
|
-
const
|
|
626
|
-
const recordType = recordTable.value_type();
|
|
628
|
+
const recordType = getRecordValueType(recordTable);
|
|
627
629
|
const standard =
|
|
628
|
-
normalizeStringField(
|
|
630
|
+
normalizeStringField(recordTable.standard()) ??
|
|
629
631
|
STANDARD_BY_RECORD_TYPE[recordType] ??
|
|
630
632
|
null;
|
|
631
633
|
const expectedStandard =
|
|
@@ -644,10 +646,7 @@ export function decodePublicationRecordCollection(bytes) {
|
|
|
644
646
|
if (!valueMeta) {
|
|
645
647
|
throw new Error(`REC trailer record ${index} is missing a value.`);
|
|
646
648
|
}
|
|
647
|
-
let value =
|
|
648
|
-
standard === "ENC" || standard === "PNM"
|
|
649
|
-
? null
|
|
650
|
-
: unpackedRecord?.value ?? null;
|
|
649
|
+
let value = null;
|
|
651
650
|
if (standard === "ENC") {
|
|
652
651
|
const encTable = recordTable.value(new ENC());
|
|
653
652
|
if (!encTable) {
|
|
@@ -684,7 +683,9 @@ export function decodePublicationRecordCollection(bytes) {
|
|
|
684
683
|
});
|
|
685
684
|
}
|
|
686
685
|
return {
|
|
687
|
-
version:
|
|
686
|
+
version:
|
|
687
|
+
normalizeStringField(collectionTable.version()) ??
|
|
688
|
+
DEFAULT_RECORD_COLLECTION_VERSION,
|
|
688
689
|
records,
|
|
689
690
|
enc,
|
|
690
691
|
pnm,
|