@peerbit/log 6.1.1 → 6.2.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/dist/benchmark/native-graph.js +447 -5
- package/dist/benchmark/native-graph.js.map +1 -1
- package/dist/src/clock.d.ts +1 -0
- package/dist/src/clock.d.ts.map +1 -1
- package/dist/src/clock.js +32 -0
- package/dist/src/clock.js.map +1 -1
- package/dist/src/entry-create.d.ts +1 -0
- package/dist/src/entry-create.d.ts.map +1 -1
- package/dist/src/entry-create.js.map +1 -1
- package/dist/src/entry-index.d.ts +288 -12
- package/dist/src/entry-index.d.ts.map +1 -1
- package/dist/src/entry-index.js +1478 -33
- package/dist/src/entry-index.js.map +1 -1
- package/dist/src/entry-v0.d.ts +184 -1
- package/dist/src/entry-v0.d.ts.map +1 -1
- package/dist/src/entry-v0.js +1021 -12
- package/dist/src/entry-v0.js.map +1 -1
- package/dist/src/entry.d.ts +73 -1
- package/dist/src/entry.d.ts.map +1 -1
- package/dist/src/entry.js +124 -1
- package/dist/src/entry.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/log.d.ts +62 -13
- package/dist/src/log.d.ts.map +1 -1
- package/dist/src/log.js +2282 -100
- package/dist/src/log.js.map +1 -1
- package/dist/src/runtime.d.ts +2 -0
- package/dist/src/runtime.d.ts.map +1 -0
- package/dist/src/runtime.js +10 -0
- package/dist/src/runtime.js.map +1 -0
- package/dist/src/trim.d.ts +14 -2
- package/dist/src/trim.d.ts.map +1 -1
- package/dist/src/trim.js +92 -4
- package/dist/src/trim.js.map +1 -1
- package/package.json +18 -15
- package/src/clock.ts +34 -0
- package/src/entry-create.ts +1 -0
- package/src/entry-index.ts +2232 -68
- package/src/entry-v0.ts +1488 -13
- package/src/entry.ts +235 -1
- package/src/index.ts +7 -1
- package/src/log.ts +3246 -206
- package/src/runtime.ts +16 -0
- package/src/trim.ts +133 -7
package/dist/src/entry-v0.js
CHANGED
|
@@ -32,9 +32,17 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
|
|
|
32
32
|
}
|
|
33
33
|
return useValue ? value : void 0;
|
|
34
34
|
};
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
36
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
37
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
38
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return path;
|
|
42
|
+
};
|
|
43
|
+
import { deserialize, field, fixedArray, option, serialize, variant, vec, } from "@dao-xyz/borsh";
|
|
44
|
+
import { calculateRawCid } from "@peerbit/blocks-interface";
|
|
45
|
+
import { AccessError, DecryptedThing, Ed25519Keypair, Ed25519PublicKey, MaybeEncrypted, PublicSignKey, SignatureWithKey, X25519Keypair, X25519PublicKey, randomBytes, sha256Base64, toBase64, } from "@peerbit/crypto";
|
|
38
46
|
import { verify } from "@peerbit/crypto";
|
|
39
47
|
import {} from "@peerbit/keychain";
|
|
40
48
|
import { compare } from "uint8arrays";
|
|
@@ -42,12 +50,223 @@ import { LamportClock as Clock, HLC, Timestamp } from "./clock.js";
|
|
|
42
50
|
import { NO_ENCODING } from "./encoding.js";
|
|
43
51
|
import { ShallowEntry, ShallowMeta } from "./entry-shallow.js";
|
|
44
52
|
import { EntryType } from "./entry-type.js";
|
|
45
|
-
import { Entry } from "./entry.js";
|
|
53
|
+
import { Entry, } from "./entry.js";
|
|
46
54
|
import { logger as baseLogger } from "./logger.js";
|
|
47
55
|
import { Payload } from "./payload.js";
|
|
56
|
+
import { canUseOptionalNativeModuleImports } from "./runtime.js";
|
|
48
57
|
import { equals } from "./utils.js";
|
|
49
58
|
const log = baseLogger.newScope("entry-v0");
|
|
50
59
|
const traceLogger = log.trace;
|
|
60
|
+
const RANDOM_GID_BYTES = 32;
|
|
61
|
+
const RANDOM_GID_POOL_SIZE = 64;
|
|
62
|
+
const NATIVE_RAW_CID_BATCH_MIN_BYTES = 1 << 20;
|
|
63
|
+
let randomGidPool = [];
|
|
64
|
+
const createRandomGid = () => {
|
|
65
|
+
if (randomGidPool.length === 0) {
|
|
66
|
+
const bytes = randomBytes(RANDOM_GID_BYTES * RANDOM_GID_POOL_SIZE);
|
|
67
|
+
randomGidPool = new Array(RANDOM_GID_POOL_SIZE);
|
|
68
|
+
for (let i = 0; i < RANDOM_GID_POOL_SIZE; i++) {
|
|
69
|
+
const offset = i * RANDOM_GID_BYTES;
|
|
70
|
+
randomGidPool[i] = toBase64(bytes.subarray(offset, offset + RANDOM_GID_BYTES));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return randomGidPool.pop();
|
|
74
|
+
};
|
|
75
|
+
let nativeEntryV0EncoderPromise;
|
|
76
|
+
let nativeEntryV0EncoderLoaded = false;
|
|
77
|
+
let nativeEntryV0Encoder;
|
|
78
|
+
const isPromiseLike = (value) => !!value && typeof value.then === "function";
|
|
79
|
+
const getSynchronousBlockBytes = (store, cid) => {
|
|
80
|
+
const value = store?.get?.(cid);
|
|
81
|
+
return value instanceof Uint8Array ? value : undefined;
|
|
82
|
+
};
|
|
83
|
+
const nativeEntryV0EncoderFromModule = (mod) => {
|
|
84
|
+
if (!mod.encodeEntryV0Signable ||
|
|
85
|
+
!mod.encodeEntryV0Storage ||
|
|
86
|
+
!mod.calculateRawCidV1) {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
encodeEntryV0Signable: mod.encodeEntryV0Signable,
|
|
91
|
+
encodeEntryV0Storage: mod.encodeEntryV0Storage,
|
|
92
|
+
encodeEntryV0StorageWithCid: mod.encodeEntryV0StorageWithCid,
|
|
93
|
+
prepareEntryV0PlainChain: mod.prepareEntryV0PlainChain,
|
|
94
|
+
prepareEntryV0PlainEntry: mod.prepareEntryV0PlainEntry,
|
|
95
|
+
calculateRawCidV1: mod.calculateRawCidV1,
|
|
96
|
+
calculateRawCidV1Batch: mod.calculateRawCidV1Batch,
|
|
97
|
+
entryV0PlainPayloadDataFromStorage: mod.entryV0PlainPayloadDataFromStorage,
|
|
98
|
+
prepareRawEntryV0Batch: mod.prepareRawEntryV0Batch,
|
|
99
|
+
verifyEd25519Batch: mod.verifyEd25519Batch,
|
|
100
|
+
verifyEntryV0Ed25519Batch: mod.verifyEntryV0Ed25519Batch,
|
|
101
|
+
verifyEntryV0Ed25519StorageBatch: mod.verifyEntryV0Ed25519StorageBatch,
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
const loadNativeEntryV0Encoder = () => {
|
|
105
|
+
if (nativeEntryV0EncoderLoaded) {
|
|
106
|
+
return nativeEntryV0Encoder;
|
|
107
|
+
}
|
|
108
|
+
if (!canUseOptionalNativeModuleImports()) {
|
|
109
|
+
nativeEntryV0EncoderLoaded = true;
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
if (!nativeEntryV0EncoderPromise) {
|
|
113
|
+
try {
|
|
114
|
+
nativeEntryV0EncoderPromise = import(__rewriteRelativeImportExtension(
|
|
115
|
+
/* @vite-ignore */ ["@peerbit", "log-rust"].join("/")))
|
|
116
|
+
.then((mod) => {
|
|
117
|
+
nativeEntryV0Encoder = nativeEntryV0EncoderFromModule(mod);
|
|
118
|
+
nativeEntryV0EncoderLoaded = true;
|
|
119
|
+
return nativeEntryV0Encoder;
|
|
120
|
+
})
|
|
121
|
+
.catch(() => {
|
|
122
|
+
nativeEntryV0Encoder = undefined;
|
|
123
|
+
nativeEntryV0EncoderLoaded = true;
|
|
124
|
+
return undefined;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
nativeEntryV0Encoder = undefined;
|
|
129
|
+
nativeEntryV0EncoderLoaded = true;
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return nativeEntryV0EncoderPromise;
|
|
134
|
+
};
|
|
135
|
+
export const calculateRawCidV1Batch = async (blocks) => {
|
|
136
|
+
if (blocks.length === 0) {
|
|
137
|
+
return [];
|
|
138
|
+
}
|
|
139
|
+
const totalBytes = blocks.reduce((sum, block) => sum + block.byteLength, 0);
|
|
140
|
+
if (totalBytes < NATIVE_RAW_CID_BATCH_MIN_BYTES) {
|
|
141
|
+
// Small raw-head messages are faster through the JS hasher because they
|
|
142
|
+
// avoid copying every block into wasm.
|
|
143
|
+
return Promise.all(blocks.map(async (bytes) => (await calculateRawCid(bytes)).cid));
|
|
144
|
+
}
|
|
145
|
+
const nativeEncoder = loadNativeEntryV0Encoder();
|
|
146
|
+
const resolvedNativeEncoder = isPromiseLike(nativeEncoder)
|
|
147
|
+
? await nativeEncoder
|
|
148
|
+
: nativeEncoder;
|
|
149
|
+
if (resolvedNativeEncoder?.calculateRawCidV1Batch) {
|
|
150
|
+
return resolvedNativeEncoder.calculateRawCidV1Batch(blocks);
|
|
151
|
+
}
|
|
152
|
+
return Promise.all(blocks.map(async (bytes) => (await calculateRawCid(bytes)).cid));
|
|
153
|
+
};
|
|
154
|
+
export const prepareRawEntryV0Batch = async (blocks) => {
|
|
155
|
+
if (blocks.length === 0) {
|
|
156
|
+
return [];
|
|
157
|
+
}
|
|
158
|
+
const nativeEncoder = loadNativeEntryV0Encoder();
|
|
159
|
+
const resolvedNativeEncoder = isPromiseLike(nativeEncoder)
|
|
160
|
+
? await nativeEncoder
|
|
161
|
+
: nativeEncoder;
|
|
162
|
+
return resolvedNativeEncoder?.prepareRawEntryV0Batch?.(blocks);
|
|
163
|
+
};
|
|
164
|
+
export const entryV0PlainPayloadDataFromStorage = async (bytes) => {
|
|
165
|
+
const nativeEncoder = loadNativeEntryV0Encoder();
|
|
166
|
+
const resolvedNativeEncoder = isPromiseLike(nativeEncoder)
|
|
167
|
+
? await nativeEncoder
|
|
168
|
+
: nativeEncoder;
|
|
169
|
+
return resolvedNativeEncoder?.entryV0PlainPayloadDataFromStorage?.(bytes);
|
|
170
|
+
};
|
|
171
|
+
export const verifyEd25519Batch = async (inputs) => {
|
|
172
|
+
if (inputs.length === 0) {
|
|
173
|
+
return [];
|
|
174
|
+
}
|
|
175
|
+
const nativeEncoder = loadNativeEntryV0Encoder();
|
|
176
|
+
const resolvedNativeEncoder = isPromiseLike(nativeEncoder)
|
|
177
|
+
? await nativeEncoder
|
|
178
|
+
: nativeEncoder;
|
|
179
|
+
return resolvedNativeEncoder?.verifyEd25519Batch?.(inputs);
|
|
180
|
+
};
|
|
181
|
+
export const verifyEntryV0Ed25519Batch = async (inputs) => {
|
|
182
|
+
if (inputs.length === 0) {
|
|
183
|
+
return [];
|
|
184
|
+
}
|
|
185
|
+
const nativeEncoder = loadNativeEntryV0Encoder();
|
|
186
|
+
const resolvedNativeEncoder = isPromiseLike(nativeEncoder)
|
|
187
|
+
? await nativeEncoder
|
|
188
|
+
: nativeEncoder;
|
|
189
|
+
return resolvedNativeEncoder?.verifyEntryV0Ed25519Batch?.(inputs);
|
|
190
|
+
};
|
|
191
|
+
export const verifyEntryV0Ed25519StorageBatch = async (blocks) => {
|
|
192
|
+
if (blocks.length === 0) {
|
|
193
|
+
return [];
|
|
194
|
+
}
|
|
195
|
+
const nativeEncoder = loadNativeEntryV0Encoder();
|
|
196
|
+
const resolvedNativeEncoder = isPromiseLike(nativeEncoder)
|
|
197
|
+
? await nativeEncoder
|
|
198
|
+
: nativeEncoder;
|
|
199
|
+
return resolvedNativeEncoder?.verifyEntryV0Ed25519StorageBatch?.(blocks);
|
|
200
|
+
};
|
|
201
|
+
export const verifyEntryV0Ed25519BatchFromEntries = async (entries) => {
|
|
202
|
+
if (entries.length === 0) {
|
|
203
|
+
return [];
|
|
204
|
+
}
|
|
205
|
+
const preparedStorageBytes = [];
|
|
206
|
+
let allHavePreparedStorageBytes = true;
|
|
207
|
+
for (const entry of entries) {
|
|
208
|
+
const bytes = Entry.getPreparedStorageBytes(entry);
|
|
209
|
+
if (!bytes) {
|
|
210
|
+
allHavePreparedStorageBytes = false;
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
preparedStorageBytes.push(bytes);
|
|
214
|
+
}
|
|
215
|
+
if (allHavePreparedStorageBytes) {
|
|
216
|
+
try {
|
|
217
|
+
const verified = await verifyEntryV0Ed25519StorageBatch(preparedStorageBytes);
|
|
218
|
+
if (verified) {
|
|
219
|
+
return verified;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
// Fall through to field extraction for encrypted or non-Ed25519 entries.
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const inputs = [];
|
|
227
|
+
for (const entry of entries) {
|
|
228
|
+
if (!(entry instanceof EntryV0)) {
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
const rawEntry = entry;
|
|
232
|
+
if (!(rawEntry._meta instanceof DecryptedThing) ||
|
|
233
|
+
!(rawEntry._payload instanceof DecryptedThing)) {
|
|
234
|
+
return undefined;
|
|
235
|
+
}
|
|
236
|
+
let signatures;
|
|
237
|
+
let meta;
|
|
238
|
+
let payload;
|
|
239
|
+
try {
|
|
240
|
+
signatures = entry.signatures;
|
|
241
|
+
meta = entry.meta;
|
|
242
|
+
payload = entry.payload;
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
return undefined;
|
|
246
|
+
}
|
|
247
|
+
if (signatures.length !== 1) {
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
250
|
+
const signature = signatures[0];
|
|
251
|
+
if (!(signature.publicKey instanceof Ed25519PublicKey) ||
|
|
252
|
+
signature.prehash !== 0) {
|
|
253
|
+
return undefined;
|
|
254
|
+
}
|
|
255
|
+
inputs.push({
|
|
256
|
+
clockId: meta.clock.id,
|
|
257
|
+
wallTime: meta.clock.timestamp.wallTime,
|
|
258
|
+
logical: meta.clock.timestamp.logical,
|
|
259
|
+
gid: meta.gid,
|
|
260
|
+
next: meta.next,
|
|
261
|
+
type: meta.type,
|
|
262
|
+
metaData: meta.data,
|
|
263
|
+
payloadData: payload.data,
|
|
264
|
+
signature: signature.signature,
|
|
265
|
+
publicKey: signature.publicKey.publicKey,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
return verifyEntryV0Ed25519Batch(inputs);
|
|
269
|
+
};
|
|
51
270
|
const isMaybeEryptionPublicKey = (o) => {
|
|
52
271
|
if (!o) {
|
|
53
272
|
return true;
|
|
@@ -225,6 +444,7 @@ let EntryV0 = (() => {
|
|
|
225
444
|
createdLocally = __runInitializers(this, _hash_extraInitializers);
|
|
226
445
|
_keychain;
|
|
227
446
|
_encoding;
|
|
447
|
+
_hashDigestBytes;
|
|
228
448
|
constructor(obj) {
|
|
229
449
|
super();
|
|
230
450
|
this._meta = obj.meta;
|
|
@@ -257,6 +477,17 @@ let EntryV0 = (() => {
|
|
|
257
477
|
await this._meta.decrypt(this._keychain);
|
|
258
478
|
return this.meta;
|
|
259
479
|
}
|
|
480
|
+
getMetaBytes() {
|
|
481
|
+
try {
|
|
482
|
+
return this._meta.decrypted._data;
|
|
483
|
+
}
|
|
484
|
+
catch {
|
|
485
|
+
return undefined;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
getHashDigestBytes() {
|
|
489
|
+
return this._hashDigestBytes;
|
|
490
|
+
}
|
|
260
491
|
async getClock() {
|
|
261
492
|
return (await this.getMeta()).clock;
|
|
262
493
|
}
|
|
@@ -393,7 +624,738 @@ let EntryV0 = (() => {
|
|
|
393
624
|
await store.rm(this.hash);
|
|
394
625
|
}
|
|
395
626
|
static createGid(seed) {
|
|
396
|
-
return seed ? sha256Base64(seed) :
|
|
627
|
+
return seed ? sha256Base64(seed) : createRandomGid();
|
|
628
|
+
}
|
|
629
|
+
static createGids(count) {
|
|
630
|
+
if (count === 0) {
|
|
631
|
+
return [];
|
|
632
|
+
}
|
|
633
|
+
const bytes = randomBytes(count * RANDOM_GID_BYTES);
|
|
634
|
+
const gids = new Array(count);
|
|
635
|
+
for (let i = 0; i < count; i++) {
|
|
636
|
+
const offset = i * RANDOM_GID_BYTES;
|
|
637
|
+
gids[i] = toBase64(bytes.subarray(offset, offset + RANDOM_GID_BYTES));
|
|
638
|
+
}
|
|
639
|
+
return gids;
|
|
640
|
+
}
|
|
641
|
+
static async createPlainAppendChain(properties) {
|
|
642
|
+
return (await EntryV0.createPlainAppendChainBatch(properties))?.entries;
|
|
643
|
+
}
|
|
644
|
+
static async createPlainAppendEntriesBatch(properties) {
|
|
645
|
+
if (!properties.deferStore) {
|
|
646
|
+
return undefined;
|
|
647
|
+
}
|
|
648
|
+
if (!(properties.identity instanceof Ed25519Keypair)) {
|
|
649
|
+
return undefined;
|
|
650
|
+
}
|
|
651
|
+
const nativeCommit = properties.nativeGraph?.prepareEntryV0PlainEntriesCommit;
|
|
652
|
+
if (!nativeCommit) {
|
|
653
|
+
return undefined;
|
|
654
|
+
}
|
|
655
|
+
if (properties.meta.gids.length !== properties.data.length ||
|
|
656
|
+
(properties.meta.nexts &&
|
|
657
|
+
properties.meta.nexts.length !== properties.data.length) ||
|
|
658
|
+
(properties.payloadDatas &&
|
|
659
|
+
properties.payloadDatas.length !== properties.data.length)) {
|
|
660
|
+
throw new Error("Expected one gid and next list per entry");
|
|
661
|
+
}
|
|
662
|
+
const clocks = properties.meta.clocks();
|
|
663
|
+
if (clocks.length !== properties.data.length) {
|
|
664
|
+
throw new Error("Expected one clock per entry");
|
|
665
|
+
}
|
|
666
|
+
for (let i = 0; i < clocks.length; i++) {
|
|
667
|
+
for (const next of properties.meta.nexts?.[i] ?? []) {
|
|
668
|
+
if (Timestamp.compare(next.meta.clock.timestamp, clocks[i].timestamp) >=
|
|
669
|
+
0) {
|
|
670
|
+
throw new Error("Expecting next(s) to happen before entry, got: " +
|
|
671
|
+
next.meta.clock.timestamp +
|
|
672
|
+
" > " +
|
|
673
|
+
clocks[i].timestamp);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
const payloadDatas = properties.payloadDatas ??
|
|
678
|
+
properties.data.map((data) => properties.encoding.encoder(data));
|
|
679
|
+
const input = {
|
|
680
|
+
clockId: properties.identity.publicKey.bytes,
|
|
681
|
+
privateKey: properties.identity.privateKey.privateKey,
|
|
682
|
+
publicKey: properties.identity.publicKey.publicKey,
|
|
683
|
+
wallTimes: clocks.map((clock) => clock.timestamp.wallTime),
|
|
684
|
+
logicals: clocks.map((clock) => clock.timestamp.logical),
|
|
685
|
+
gids: properties.meta.gids,
|
|
686
|
+
nexts: properties.meta.nexts?.map((nexts) => nexts.map((next) => next.hash)),
|
|
687
|
+
type: properties.meta.type,
|
|
688
|
+
metaDatas: properties.meta.datas,
|
|
689
|
+
payloadDatas,
|
|
690
|
+
};
|
|
691
|
+
const preparedValue = nativeCommit.call(properties.nativeGraph, input, properties.nativeBlockStore);
|
|
692
|
+
const prepared = isPromiseLike(preparedValue)
|
|
693
|
+
? await preparedValue
|
|
694
|
+
: preparedValue;
|
|
695
|
+
if (!prepared) {
|
|
696
|
+
return undefined;
|
|
697
|
+
}
|
|
698
|
+
if (prepared.length !== properties.data.length) {
|
|
699
|
+
throw new Error("Unexpected prepared entry batch length");
|
|
700
|
+
}
|
|
701
|
+
const entries = [];
|
|
702
|
+
const shallowEntries = [];
|
|
703
|
+
const appendFacts = [];
|
|
704
|
+
const nativeEntries = [];
|
|
705
|
+
const entryType = properties.meta.type ?? EntryType.APPEND;
|
|
706
|
+
for (let index = 0; index < prepared.length; index++) {
|
|
707
|
+
const preparedEntry = prepared[index];
|
|
708
|
+
const clock = clocks[index];
|
|
709
|
+
const entryGid = properties.meta.gids[index];
|
|
710
|
+
const metaData = properties.meta.datas?.[index];
|
|
711
|
+
const meta = new Meta({
|
|
712
|
+
clock,
|
|
713
|
+
gid: entryGid,
|
|
714
|
+
type: entryType,
|
|
715
|
+
data: metaData,
|
|
716
|
+
next: preparedEntry.next,
|
|
717
|
+
});
|
|
718
|
+
const payloadSize = payloadDatas[index].byteLength;
|
|
719
|
+
const payload = properties.cachePreparedEntries === false
|
|
720
|
+
? undefined
|
|
721
|
+
: new Payload({
|
|
722
|
+
data: payloadDatas[index],
|
|
723
|
+
value: properties.data[index],
|
|
724
|
+
encoding: properties.encoding,
|
|
725
|
+
});
|
|
726
|
+
const signature = properties.cachePreparedEntries === false
|
|
727
|
+
? undefined
|
|
728
|
+
: new SignatureWithKey({
|
|
729
|
+
signature: preparedEntry.signature,
|
|
730
|
+
publicKey: properties.identity.publicKey,
|
|
731
|
+
prehash: 0,
|
|
732
|
+
});
|
|
733
|
+
const entry = new EntryV0({
|
|
734
|
+
meta: new DecryptedThing({
|
|
735
|
+
data: preparedEntry.metaBytes,
|
|
736
|
+
value: meta,
|
|
737
|
+
}),
|
|
738
|
+
payload: new DecryptedThing({
|
|
739
|
+
data: preparedEntry.payloadBytes,
|
|
740
|
+
value: payload,
|
|
741
|
+
}),
|
|
742
|
+
signatures: new Signatures({
|
|
743
|
+
signatures: [
|
|
744
|
+
new DecryptedThing({
|
|
745
|
+
data: preparedEntry.signatureBytes,
|
|
746
|
+
value: signature,
|
|
747
|
+
}),
|
|
748
|
+
],
|
|
749
|
+
}),
|
|
750
|
+
createdLocally: true,
|
|
751
|
+
});
|
|
752
|
+
if (properties.cachePreparedEntries === false) {
|
|
753
|
+
entry.hash = preparedEntry.cid;
|
|
754
|
+
entry.size = preparedEntry.byteLength;
|
|
755
|
+
}
|
|
756
|
+
else {
|
|
757
|
+
if (!preparedEntry.bytes) {
|
|
758
|
+
throw new Error("Missing prepared entry bytes");
|
|
759
|
+
}
|
|
760
|
+
entry.hash = Entry.prepareMultihashBytes(entry, preparedEntry.bytes, preparedEntry.cid);
|
|
761
|
+
}
|
|
762
|
+
entry._hashDigestBytes = preparedEntry.hashDigestBytes;
|
|
763
|
+
const shallowEntry = new ShallowEntry({
|
|
764
|
+
hash: entry.hash,
|
|
765
|
+
payloadSize,
|
|
766
|
+
head: true,
|
|
767
|
+
meta: new ShallowMeta({
|
|
768
|
+
gid: entryGid,
|
|
769
|
+
data: metaData,
|
|
770
|
+
clock,
|
|
771
|
+
next: preparedEntry.next,
|
|
772
|
+
type: entryType,
|
|
773
|
+
}),
|
|
774
|
+
});
|
|
775
|
+
const nativeEntry = properties.cachePreparedEntries === false
|
|
776
|
+
? undefined
|
|
777
|
+
: {
|
|
778
|
+
hash: entry.hash,
|
|
779
|
+
gid: entryGid,
|
|
780
|
+
next: preparedEntry.next,
|
|
781
|
+
type: entryType,
|
|
782
|
+
head: true,
|
|
783
|
+
payloadSize,
|
|
784
|
+
data: metaData,
|
|
785
|
+
clock: {
|
|
786
|
+
timestamp: {
|
|
787
|
+
wallTime: clock.timestamp.wallTime,
|
|
788
|
+
logical: clock.timestamp.logical,
|
|
789
|
+
},
|
|
790
|
+
},
|
|
791
|
+
};
|
|
792
|
+
if (properties.cachePreparedEntries !== false) {
|
|
793
|
+
Entry.prepareShallowEntry(entry, shallowEntry);
|
|
794
|
+
Entry.prepareNativeLogEntry(entry, nativeEntry);
|
|
795
|
+
entry.init({ encoding: properties.encoding });
|
|
796
|
+
}
|
|
797
|
+
entries.push(entry);
|
|
798
|
+
shallowEntries.push(shallowEntry);
|
|
799
|
+
appendFacts.push({
|
|
800
|
+
hash: entry.hash,
|
|
801
|
+
gid: entryGid,
|
|
802
|
+
next: preparedEntry.next,
|
|
803
|
+
wallTime: clock.timestamp.wallTime,
|
|
804
|
+
logical: clock.timestamp.logical,
|
|
805
|
+
clockId: clock.id,
|
|
806
|
+
type: entryType,
|
|
807
|
+
metaData,
|
|
808
|
+
payloadSize,
|
|
809
|
+
metaBytes: preparedEntry.metaBytes,
|
|
810
|
+
hashDigestBytes: preparedEntry.hashDigestBytes,
|
|
811
|
+
});
|
|
812
|
+
if (nativeEntry) {
|
|
813
|
+
nativeEntries.push(nativeEntry);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
return {
|
|
817
|
+
entries,
|
|
818
|
+
shallowEntries,
|
|
819
|
+
appendFacts,
|
|
820
|
+
nativeEntries,
|
|
821
|
+
nativeGraphUpdated: true,
|
|
822
|
+
nativeBlocksCommitted: true,
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
static createPlainAppendChainCommitOnly(properties) {
|
|
826
|
+
if (!properties.deferStore || properties.data.length !== 1) {
|
|
827
|
+
return undefined;
|
|
828
|
+
}
|
|
829
|
+
if (!(properties.identity instanceof Ed25519Keypair)) {
|
|
830
|
+
return undefined;
|
|
831
|
+
}
|
|
832
|
+
if (!properties.nativeGraph?.prepareEntryV0PlainEntryCommit &&
|
|
833
|
+
!properties.nativeGraph?.prepareEntryV0PlainEntryAndPut) {
|
|
834
|
+
return undefined;
|
|
835
|
+
}
|
|
836
|
+
const nexts = properties.meta?.next ?? [];
|
|
837
|
+
const nextHashes = [];
|
|
838
|
+
let gid = null;
|
|
839
|
+
if (nexts.length > 0) {
|
|
840
|
+
if (properties.meta?.gid) {
|
|
841
|
+
throw new Error("Expecting '.meta.gid' property to be undefined if '.meta.next' is provided");
|
|
842
|
+
}
|
|
843
|
+
for (const next of nexts) {
|
|
844
|
+
if (!next.hash) {
|
|
845
|
+
throw new Error("Expecting hash to be defined to next entries");
|
|
846
|
+
}
|
|
847
|
+
nextHashes.push(next.hash);
|
|
848
|
+
gid =
|
|
849
|
+
gid == null
|
|
850
|
+
? next.meta.gid
|
|
851
|
+
: next.meta.gid < gid
|
|
852
|
+
? next.meta.gid
|
|
853
|
+
: gid;
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
else if (properties.meta?.gid) {
|
|
857
|
+
gid = properties.meta.gid;
|
|
858
|
+
}
|
|
859
|
+
else {
|
|
860
|
+
const createdGid = EntryV0.createGid(properties.meta?.gidSeed);
|
|
861
|
+
return isPromiseLike(createdGid)
|
|
862
|
+
? createdGid.then((resolvedGid) => EntryV0.finishPlainAppendChainCommitOnly(properties, nexts, nextHashes, resolvedGid))
|
|
863
|
+
: EntryV0.finishPlainAppendChainCommitOnly(properties, nexts, nextHashes, createdGid);
|
|
864
|
+
}
|
|
865
|
+
return EntryV0.finishPlainAppendChainCommitOnly(properties, nexts, nextHashes, gid);
|
|
866
|
+
}
|
|
867
|
+
static finishPlainAppendChainCommitOnly(properties, nexts, nextHashes, gid) {
|
|
868
|
+
if (!properties.nativeGraph ||
|
|
869
|
+
!(properties.identity instanceof Ed25519Keypair)) {
|
|
870
|
+
return undefined;
|
|
871
|
+
}
|
|
872
|
+
const nativeGraph = properties.nativeGraph;
|
|
873
|
+
const identity = properties.identity;
|
|
874
|
+
const clocks = properties.meta?.clocks();
|
|
875
|
+
if (!clocks || clocks.length !== 1) {
|
|
876
|
+
throw new Error("Expected one clock per entry");
|
|
877
|
+
}
|
|
878
|
+
const clock = clocks[0];
|
|
879
|
+
for (const next of nexts) {
|
|
880
|
+
if (Timestamp.compare(next.meta.clock.timestamp, clock.timestamp) >= 0) {
|
|
881
|
+
throw new Error("Expecting next(s) to happen before entry, got: " +
|
|
882
|
+
next.meta.clock.timestamp +
|
|
883
|
+
" > " +
|
|
884
|
+
clock.timestamp);
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
const payloadData = properties.payloadDatas?.[0] ??
|
|
888
|
+
properties.encoding.encoder(properties.data[0]);
|
|
889
|
+
const entryType = properties.meta?.type ?? EntryType.APPEND;
|
|
890
|
+
const singleInput = {
|
|
891
|
+
clockId: identity.publicKey.bytes,
|
|
892
|
+
privateKey: identity.privateKey.privateKey,
|
|
893
|
+
publicKey: identity.publicKey.publicKey,
|
|
894
|
+
wallTime: clock.timestamp.wallTime,
|
|
895
|
+
logical: clock.timestamp.logical,
|
|
896
|
+
gid: gid,
|
|
897
|
+
next: nextHashes,
|
|
898
|
+
type: entryType,
|
|
899
|
+
metaData: properties.meta?.data,
|
|
900
|
+
payloadData,
|
|
901
|
+
includeMaterializationBytes: properties.includeMaterializationBytes,
|
|
902
|
+
includeAppendFactsBytes: properties.includeAppendFactsBytes,
|
|
903
|
+
trimLengthTo: properties.nativeTrimLengthTo,
|
|
904
|
+
resolveTrimmedEntries: properties.nativeTrimLengthTo == null ? undefined : false,
|
|
905
|
+
};
|
|
906
|
+
let nativeBlocksCommitted = false;
|
|
907
|
+
let nativeGraphUpdated = false;
|
|
908
|
+
const finishWithPreparedEntry = (preparedEntry) => {
|
|
909
|
+
if (!preparedEntry) {
|
|
910
|
+
return undefined;
|
|
911
|
+
}
|
|
912
|
+
const payloadSize = payloadData.byteLength;
|
|
913
|
+
const shallowEntry = new ShallowEntry({
|
|
914
|
+
hash: preparedEntry.cid,
|
|
915
|
+
payloadSize,
|
|
916
|
+
head: true,
|
|
917
|
+
meta: new ShallowMeta({
|
|
918
|
+
gid: gid,
|
|
919
|
+
data: properties.meta?.data,
|
|
920
|
+
clock,
|
|
921
|
+
next: preparedEntry.next,
|
|
922
|
+
type: entryType,
|
|
923
|
+
}),
|
|
924
|
+
});
|
|
925
|
+
const appendFacts = {
|
|
926
|
+
hash: preparedEntry.cid,
|
|
927
|
+
gid: gid,
|
|
928
|
+
next: preparedEntry.next,
|
|
929
|
+
wallTime: clock.timestamp.wallTime,
|
|
930
|
+
logical: clock.timestamp.logical,
|
|
931
|
+
clockId: clock.id,
|
|
932
|
+
type: entryType,
|
|
933
|
+
metaData: properties.meta?.data,
|
|
934
|
+
payloadSize,
|
|
935
|
+
metaBytes: preparedEntry.metaBytes,
|
|
936
|
+
hashDigestBytes: preparedEntry.hashDigestBytes,
|
|
937
|
+
};
|
|
938
|
+
let materialized;
|
|
939
|
+
const materializeEntry = (index = 0) => {
|
|
940
|
+
if (index !== 0) {
|
|
941
|
+
throw new Error("Prepared commit-only append only has one entry");
|
|
942
|
+
}
|
|
943
|
+
if (materialized) {
|
|
944
|
+
return materialized;
|
|
945
|
+
}
|
|
946
|
+
const payload = new Payload({
|
|
947
|
+
data: payloadData,
|
|
948
|
+
value: properties.data[0],
|
|
949
|
+
encoding: properties.encoding,
|
|
950
|
+
});
|
|
951
|
+
if (!preparedEntry.metaBytes ||
|
|
952
|
+
!preparedEntry.payloadBytes ||
|
|
953
|
+
!preparedEntry.signature ||
|
|
954
|
+
!preparedEntry.signatureBytes) {
|
|
955
|
+
const bytes = preparedEntry.bytes ??
|
|
956
|
+
getSynchronousBlockBytes(properties.nativeBlockStore, preparedEntry.cid);
|
|
957
|
+
if (!bytes) {
|
|
958
|
+
throw new Error("Missing prepared entry bytes");
|
|
959
|
+
}
|
|
960
|
+
const entry = deserialize(bytes, Entry);
|
|
961
|
+
entry.hash = preparedEntry.cid;
|
|
962
|
+
entry.size = preparedEntry.byteLength;
|
|
963
|
+
entry.createdLocally = true;
|
|
964
|
+
entry._hashDigestBytes = preparedEntry.hashDigestBytes;
|
|
965
|
+
Entry.prepareShallowEntry(entry, shallowEntry);
|
|
966
|
+
entry.init({ encoding: properties.encoding });
|
|
967
|
+
materialized = entry;
|
|
968
|
+
return entry;
|
|
969
|
+
}
|
|
970
|
+
const signature = new SignatureWithKey({
|
|
971
|
+
signature: preparedEntry.signature,
|
|
972
|
+
publicKey: properties.identity.publicKey,
|
|
973
|
+
prehash: 0,
|
|
974
|
+
});
|
|
975
|
+
const meta = new Meta({
|
|
976
|
+
clock,
|
|
977
|
+
gid: gid,
|
|
978
|
+
type: entryType,
|
|
979
|
+
data: properties.meta?.data,
|
|
980
|
+
next: preparedEntry.next,
|
|
981
|
+
});
|
|
982
|
+
const entry = new EntryV0({
|
|
983
|
+
meta: new DecryptedThing({
|
|
984
|
+
data: preparedEntry.metaBytes,
|
|
985
|
+
value: meta,
|
|
986
|
+
}),
|
|
987
|
+
payload: new DecryptedThing({
|
|
988
|
+
data: preparedEntry.payloadBytes,
|
|
989
|
+
value: payload,
|
|
990
|
+
}),
|
|
991
|
+
signatures: new Signatures({
|
|
992
|
+
signatures: [
|
|
993
|
+
new DecryptedThing({
|
|
994
|
+
data: preparedEntry.signatureBytes,
|
|
995
|
+
value: signature,
|
|
996
|
+
}),
|
|
997
|
+
],
|
|
998
|
+
}),
|
|
999
|
+
createdLocally: true,
|
|
1000
|
+
});
|
|
1001
|
+
entry.hash = preparedEntry.cid;
|
|
1002
|
+
entry.size = preparedEntry.byteLength;
|
|
1003
|
+
entry._hashDigestBytes = preparedEntry.hashDigestBytes;
|
|
1004
|
+
Entry.prepareShallowEntry(entry, shallowEntry);
|
|
1005
|
+
entry.init({ encoding: properties.encoding });
|
|
1006
|
+
materialized = entry;
|
|
1007
|
+
return entry;
|
|
1008
|
+
};
|
|
1009
|
+
const preparedBlock = preparedEntry.bytes && !nativeBlocksCommitted
|
|
1010
|
+
? Entry.preparedBlockFromBytes(preparedEntry.bytes, preparedEntry.cid)
|
|
1011
|
+
: undefined;
|
|
1012
|
+
return {
|
|
1013
|
+
materializeEntry,
|
|
1014
|
+
materializeEntries: () => [materializeEntry(0)],
|
|
1015
|
+
blocks: preparedBlock ? [preparedBlock] : undefined,
|
|
1016
|
+
shallowEntries: [shallowEntry],
|
|
1017
|
+
appendFacts: [appendFacts],
|
|
1018
|
+
trimmedNativeEntries: preparedEntry.trimmedEntries,
|
|
1019
|
+
trimmedNativeEntryHashes: preparedEntry.trimmedEntryHashes,
|
|
1020
|
+
trimmedNativeBlocksDeleted: nativeBlocksCommitted,
|
|
1021
|
+
nativeGraphUpdated,
|
|
1022
|
+
nativeBlocksCommitted,
|
|
1023
|
+
};
|
|
1024
|
+
};
|
|
1025
|
+
const prepareAndPutFallback = () => {
|
|
1026
|
+
const nativePrepareAndPut = nativeGraph.prepareEntryV0PlainEntryAndPut;
|
|
1027
|
+
const preparedEntryValue = nativePrepareAndPut
|
|
1028
|
+
? nativePrepareAndPut.call(nativeGraph, {
|
|
1029
|
+
...singleInput,
|
|
1030
|
+
})
|
|
1031
|
+
: undefined;
|
|
1032
|
+
if (isPromiseLike(preparedEntryValue)) {
|
|
1033
|
+
return preparedEntryValue.then((preparedEntry) => {
|
|
1034
|
+
nativeGraphUpdated = !!preparedEntry && !!nativePrepareAndPut;
|
|
1035
|
+
return finishWithPreparedEntry(preparedEntry);
|
|
1036
|
+
});
|
|
1037
|
+
}
|
|
1038
|
+
nativeGraphUpdated = !!preparedEntryValue && !!nativePrepareAndPut;
|
|
1039
|
+
return finishWithPreparedEntry(preparedEntryValue);
|
|
1040
|
+
};
|
|
1041
|
+
const nativeCommit = nativeGraph.prepareEntryV0PlainEntryCommit;
|
|
1042
|
+
if (nativeCommit) {
|
|
1043
|
+
const preparedEntryValue = nativeCommit.call(nativeGraph, singleInput, properties.nativeBlockStore);
|
|
1044
|
+
if (isPromiseLike(preparedEntryValue)) {
|
|
1045
|
+
return preparedEntryValue.then((preparedEntry) => {
|
|
1046
|
+
if (preparedEntry) {
|
|
1047
|
+
nativeBlocksCommitted = true;
|
|
1048
|
+
nativeGraphUpdated = true;
|
|
1049
|
+
return finishWithPreparedEntry(preparedEntry);
|
|
1050
|
+
}
|
|
1051
|
+
return prepareAndPutFallback();
|
|
1052
|
+
});
|
|
1053
|
+
}
|
|
1054
|
+
if (preparedEntryValue) {
|
|
1055
|
+
nativeBlocksCommitted = true;
|
|
1056
|
+
nativeGraphUpdated = true;
|
|
1057
|
+
return finishWithPreparedEntry(preparedEntryValue);
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
return prepareAndPutFallback();
|
|
1061
|
+
}
|
|
1062
|
+
static async createPlainAppendChainBatch(properties) {
|
|
1063
|
+
if (!properties.deferStore) {
|
|
1064
|
+
return undefined;
|
|
1065
|
+
}
|
|
1066
|
+
if (!(properties.identity instanceof Ed25519Keypair)) {
|
|
1067
|
+
return undefined;
|
|
1068
|
+
}
|
|
1069
|
+
const nativeEncoderValue = loadNativeEntryV0Encoder();
|
|
1070
|
+
const nativeEncoder = isPromiseLike(nativeEncoderValue)
|
|
1071
|
+
? await nativeEncoderValue
|
|
1072
|
+
: nativeEncoderValue;
|
|
1073
|
+
if (!nativeEncoder?.prepareEntryV0PlainChain) {
|
|
1074
|
+
return undefined;
|
|
1075
|
+
}
|
|
1076
|
+
const nexts = properties.meta?.next ?? [];
|
|
1077
|
+
const nextHashes = [];
|
|
1078
|
+
let gid = null;
|
|
1079
|
+
if (nexts.length > 0) {
|
|
1080
|
+
if (properties.meta?.gid) {
|
|
1081
|
+
throw new Error("Expecting '.meta.gid' property to be undefined if '.meta.next' is provided");
|
|
1082
|
+
}
|
|
1083
|
+
for (const next of nexts) {
|
|
1084
|
+
if (!next.hash) {
|
|
1085
|
+
throw new Error("Expecting hash to be defined to next entries");
|
|
1086
|
+
}
|
|
1087
|
+
nextHashes.push(next.hash);
|
|
1088
|
+
gid =
|
|
1089
|
+
gid == null
|
|
1090
|
+
? next.meta.gid
|
|
1091
|
+
: next.meta.gid < gid
|
|
1092
|
+
? next.meta.gid
|
|
1093
|
+
: gid;
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
else {
|
|
1097
|
+
if (properties.meta?.gid) {
|
|
1098
|
+
gid = properties.meta.gid;
|
|
1099
|
+
}
|
|
1100
|
+
else {
|
|
1101
|
+
const createdGid = EntryV0.createGid(properties.meta?.gidSeed);
|
|
1102
|
+
gid = isPromiseLike(createdGid) ? await createdGid : createdGid;
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
const clocks = properties.meta?.clocks();
|
|
1106
|
+
if (!clocks || clocks.length !== properties.data.length) {
|
|
1107
|
+
throw new Error("Expected one clock per entry");
|
|
1108
|
+
}
|
|
1109
|
+
for (const next of nexts) {
|
|
1110
|
+
if (Timestamp.compare(next.meta.clock.timestamp, clocks[0].timestamp) >= 0) {
|
|
1111
|
+
throw new Error("Expecting next(s) to happen before entry, got: " +
|
|
1112
|
+
next.meta.clock.timestamp +
|
|
1113
|
+
" > " +
|
|
1114
|
+
clocks[0].timestamp);
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
for (let i = 1; i < clocks.length; i++) {
|
|
1118
|
+
if (Timestamp.compare(clocks[i - 1].timestamp, clocks[i].timestamp) >= 0) {
|
|
1119
|
+
throw new Error("Expecting generated clocks to increase across appendMany");
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
const entryType = properties.meta?.type ?? EntryType.APPEND;
|
|
1123
|
+
const clockId = properties.identity.publicKey.bytes;
|
|
1124
|
+
const privateKey = properties.identity.privateKey.privateKey;
|
|
1125
|
+
const publicKey = properties.identity.publicKey.publicKey;
|
|
1126
|
+
let nativeBlocksCommitted = false;
|
|
1127
|
+
let nativeGraphUpdated = false;
|
|
1128
|
+
let prepared;
|
|
1129
|
+
let payloadDatas;
|
|
1130
|
+
if (properties.data.length === 1) {
|
|
1131
|
+
const clock = clocks[0];
|
|
1132
|
+
const payloadData = properties.payloadDatas?.[0] ??
|
|
1133
|
+
properties.encoding.encoder(properties.data[0]);
|
|
1134
|
+
const singleInput = {
|
|
1135
|
+
clockId,
|
|
1136
|
+
privateKey,
|
|
1137
|
+
publicKey,
|
|
1138
|
+
wallTime: clock.timestamp.wallTime,
|
|
1139
|
+
logical: clock.timestamp.logical,
|
|
1140
|
+
gid: gid,
|
|
1141
|
+
next: nextHashes,
|
|
1142
|
+
type: entryType,
|
|
1143
|
+
metaData: properties.meta?.data,
|
|
1144
|
+
payloadData,
|
|
1145
|
+
};
|
|
1146
|
+
const nativeCommit = properties.nativeGraph?.prepareEntryV0PlainEntryCommit;
|
|
1147
|
+
const preparedEntryValue = nativeCommit
|
|
1148
|
+
? nativeCommit.call(properties.nativeGraph, singleInput, properties.nativeBlockStore)
|
|
1149
|
+
: undefined;
|
|
1150
|
+
const preparedEntry = isPromiseLike(preparedEntryValue)
|
|
1151
|
+
? await preparedEntryValue
|
|
1152
|
+
: preparedEntryValue;
|
|
1153
|
+
if (preparedEntry) {
|
|
1154
|
+
nativeBlocksCommitted = true;
|
|
1155
|
+
nativeGraphUpdated = true;
|
|
1156
|
+
prepared = [preparedEntry];
|
|
1157
|
+
payloadDatas = [payloadData];
|
|
1158
|
+
}
|
|
1159
|
+
else {
|
|
1160
|
+
const nativePrepareAndPut = properties.nativeGraph?.prepareEntryV0PlainEntryAndPut;
|
|
1161
|
+
const scalarPreparedEntryValue = nativePrepareAndPut
|
|
1162
|
+
? nativePrepareAndPut.call(properties.nativeGraph, singleInput)
|
|
1163
|
+
: nativeEncoder.prepareEntryV0PlainEntry?.(singleInput);
|
|
1164
|
+
const scalarPreparedEntry = isPromiseLike(scalarPreparedEntryValue)
|
|
1165
|
+
? await scalarPreparedEntryValue
|
|
1166
|
+
: scalarPreparedEntryValue;
|
|
1167
|
+
if (scalarPreparedEntry) {
|
|
1168
|
+
nativeGraphUpdated = !!nativePrepareAndPut;
|
|
1169
|
+
prepared = [scalarPreparedEntry];
|
|
1170
|
+
payloadDatas = [payloadData];
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
if (!prepared) {
|
|
1175
|
+
const wallTimes = new Array(properties.data.length);
|
|
1176
|
+
const logicals = new Array(properties.data.length);
|
|
1177
|
+
const metaDatas = new Array(properties.data.length);
|
|
1178
|
+
if (properties.payloadDatas &&
|
|
1179
|
+
properties.payloadDatas.length !== properties.data.length) {
|
|
1180
|
+
throw new Error("Expected one payload data value per entry");
|
|
1181
|
+
}
|
|
1182
|
+
payloadDatas = properties.payloadDatas
|
|
1183
|
+
? [...properties.payloadDatas]
|
|
1184
|
+
: new Array(properties.data.length);
|
|
1185
|
+
for (let i = 0; i < properties.data.length; i++) {
|
|
1186
|
+
const clock = clocks[i];
|
|
1187
|
+
wallTimes[i] = clock.timestamp.wallTime;
|
|
1188
|
+
logicals[i] = clock.timestamp.logical;
|
|
1189
|
+
metaDatas[i] = properties.meta?.data;
|
|
1190
|
+
payloadDatas[i] ??= properties.encoding.encoder(properties.data[i]);
|
|
1191
|
+
}
|
|
1192
|
+
const nativePlainChainInput = {
|
|
1193
|
+
clockId,
|
|
1194
|
+
privateKey,
|
|
1195
|
+
publicKey,
|
|
1196
|
+
wallTimes,
|
|
1197
|
+
logicals,
|
|
1198
|
+
gid: gid,
|
|
1199
|
+
initialNext: nextHashes,
|
|
1200
|
+
type: entryType,
|
|
1201
|
+
metaDatas,
|
|
1202
|
+
payloadDatas,
|
|
1203
|
+
};
|
|
1204
|
+
const nativeCommit = properties.nativeGraph?.prepareEntryV0PlainChainCommit;
|
|
1205
|
+
const preparedValue = nativeCommit
|
|
1206
|
+
? nativeCommit.call(properties.nativeGraph, nativePlainChainInput, properties.nativeBlockStore)
|
|
1207
|
+
: undefined;
|
|
1208
|
+
prepared = isPromiseLike(preparedValue)
|
|
1209
|
+
? await preparedValue
|
|
1210
|
+
: preparedValue;
|
|
1211
|
+
if (prepared) {
|
|
1212
|
+
nativeBlocksCommitted = true;
|
|
1213
|
+
nativeGraphUpdated = true;
|
|
1214
|
+
}
|
|
1215
|
+
else {
|
|
1216
|
+
const nativePrepareAndPut = properties.nativeGraph?.prepareEntryV0PlainChainAndPut;
|
|
1217
|
+
const preparedFallbackValue = nativePrepareAndPut
|
|
1218
|
+
? nativePrepareAndPut.call(properties.nativeGraph, nativePlainChainInput)
|
|
1219
|
+
: nativeEncoder.prepareEntryV0PlainChain(nativePlainChainInput);
|
|
1220
|
+
prepared = isPromiseLike(preparedFallbackValue)
|
|
1221
|
+
? await preparedFallbackValue
|
|
1222
|
+
: preparedFallbackValue;
|
|
1223
|
+
nativeGraphUpdated = !!nativePrepareAndPut;
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
const entries = [];
|
|
1227
|
+
const blocks = [];
|
|
1228
|
+
const shallowEntries = [];
|
|
1229
|
+
const appendFacts = [];
|
|
1230
|
+
const nativeEntries = [];
|
|
1231
|
+
if (!payloadDatas) {
|
|
1232
|
+
throw new Error("Expected payload data for prepared append chain");
|
|
1233
|
+
}
|
|
1234
|
+
for (let index = 0; index < prepared.length; index++) {
|
|
1235
|
+
const preparedEntry = prepared[index];
|
|
1236
|
+
const clock = clocks[index];
|
|
1237
|
+
const meta = new Meta({
|
|
1238
|
+
clock,
|
|
1239
|
+
gid: gid,
|
|
1240
|
+
type: entryType,
|
|
1241
|
+
data: properties.meta?.data,
|
|
1242
|
+
next: preparedEntry.next,
|
|
1243
|
+
});
|
|
1244
|
+
const payloadSize = payloadDatas[index].byteLength;
|
|
1245
|
+
const payload = properties.cachePreparedEntries === false
|
|
1246
|
+
? undefined
|
|
1247
|
+
: new Payload({
|
|
1248
|
+
data: payloadDatas[index],
|
|
1249
|
+
value: properties.data[index],
|
|
1250
|
+
encoding: properties.encoding,
|
|
1251
|
+
});
|
|
1252
|
+
const signature = properties.cachePreparedEntries === false
|
|
1253
|
+
? undefined
|
|
1254
|
+
: new SignatureWithKey({
|
|
1255
|
+
signature: preparedEntry.signature,
|
|
1256
|
+
publicKey: properties.identity.publicKey,
|
|
1257
|
+
prehash: 0,
|
|
1258
|
+
});
|
|
1259
|
+
const entry = new EntryV0({
|
|
1260
|
+
meta: new DecryptedThing({
|
|
1261
|
+
data: preparedEntry.metaBytes,
|
|
1262
|
+
value: meta,
|
|
1263
|
+
}),
|
|
1264
|
+
payload: new DecryptedThing({
|
|
1265
|
+
data: preparedEntry.payloadBytes,
|
|
1266
|
+
value: payload,
|
|
1267
|
+
}),
|
|
1268
|
+
signatures: new Signatures({
|
|
1269
|
+
signatures: [
|
|
1270
|
+
new DecryptedThing({
|
|
1271
|
+
data: preparedEntry.signatureBytes,
|
|
1272
|
+
value: signature,
|
|
1273
|
+
}),
|
|
1274
|
+
],
|
|
1275
|
+
}),
|
|
1276
|
+
createdLocally: true,
|
|
1277
|
+
});
|
|
1278
|
+
const preparedBlock = preparedEntry.bytes && !nativeBlocksCommitted
|
|
1279
|
+
? Entry.preparedBlockFromBytes(preparedEntry.bytes, preparedEntry.cid)
|
|
1280
|
+
: undefined;
|
|
1281
|
+
if (properties.cachePreparedEntries === false) {
|
|
1282
|
+
entry.hash = preparedEntry.cid;
|
|
1283
|
+
entry.size = preparedEntry.byteLength;
|
|
1284
|
+
}
|
|
1285
|
+
else {
|
|
1286
|
+
if (!preparedEntry.bytes) {
|
|
1287
|
+
throw new Error("Missing prepared entry bytes");
|
|
1288
|
+
}
|
|
1289
|
+
entry.hash = Entry.prepareMultihashBytes(entry, preparedEntry.bytes, preparedEntry.cid);
|
|
1290
|
+
}
|
|
1291
|
+
entry._hashDigestBytes = preparedEntry.hashDigestBytes;
|
|
1292
|
+
const shallowEntry = new ShallowEntry({
|
|
1293
|
+
hash: entry.hash,
|
|
1294
|
+
payloadSize,
|
|
1295
|
+
head: index === prepared.length - 1,
|
|
1296
|
+
meta: new ShallowMeta({
|
|
1297
|
+
gid: gid,
|
|
1298
|
+
data: properties.meta?.data,
|
|
1299
|
+
clock,
|
|
1300
|
+
next: preparedEntry.next,
|
|
1301
|
+
type: entryType,
|
|
1302
|
+
}),
|
|
1303
|
+
});
|
|
1304
|
+
const nativeEntry = nativeGraphUpdated && properties.cachePreparedEntries === false
|
|
1305
|
+
? undefined
|
|
1306
|
+
: {
|
|
1307
|
+
hash: entry.hash,
|
|
1308
|
+
gid: gid,
|
|
1309
|
+
next: preparedEntry.next,
|
|
1310
|
+
type: entryType,
|
|
1311
|
+
head: index === prepared.length - 1,
|
|
1312
|
+
payloadSize,
|
|
1313
|
+
data: properties.meta?.data,
|
|
1314
|
+
clock: {
|
|
1315
|
+
timestamp: {
|
|
1316
|
+
wallTime: clock.timestamp.wallTime,
|
|
1317
|
+
logical: clock.timestamp.logical,
|
|
1318
|
+
},
|
|
1319
|
+
},
|
|
1320
|
+
};
|
|
1321
|
+
if (properties.cachePreparedEntries !== false) {
|
|
1322
|
+
Entry.prepareShallowEntry(entry, shallowEntry);
|
|
1323
|
+
Entry.prepareNativeLogEntry(entry, nativeEntry);
|
|
1324
|
+
}
|
|
1325
|
+
if (properties.cachePreparedEntries !== false) {
|
|
1326
|
+
entry.init({ encoding: properties.encoding });
|
|
1327
|
+
}
|
|
1328
|
+
entries.push(entry);
|
|
1329
|
+
if (preparedBlock) {
|
|
1330
|
+
blocks.push(preparedBlock);
|
|
1331
|
+
}
|
|
1332
|
+
shallowEntries.push(shallowEntry);
|
|
1333
|
+
appendFacts.push({
|
|
1334
|
+
hash: entry.hash,
|
|
1335
|
+
gid: gid,
|
|
1336
|
+
next: preparedEntry.next,
|
|
1337
|
+
wallTime: clock.timestamp.wallTime,
|
|
1338
|
+
logical: clock.timestamp.logical,
|
|
1339
|
+
clockId: clock.id,
|
|
1340
|
+
type: entryType,
|
|
1341
|
+
metaData: properties.meta?.data,
|
|
1342
|
+
payloadSize,
|
|
1343
|
+
metaBytes: preparedEntry.metaBytes,
|
|
1344
|
+
hashDigestBytes: preparedEntry.hashDigestBytes,
|
|
1345
|
+
});
|
|
1346
|
+
if (nativeEntry) {
|
|
1347
|
+
nativeEntries.push(nativeEntry);
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
return {
|
|
1351
|
+
entries,
|
|
1352
|
+
blocks: blocks.length > 0 ? blocks : undefined,
|
|
1353
|
+
shallowEntries,
|
|
1354
|
+
appendFacts,
|
|
1355
|
+
nativeEntries,
|
|
1356
|
+
nativeGraphUpdated,
|
|
1357
|
+
nativeBlocksCommitted,
|
|
1358
|
+
};
|
|
397
1359
|
}
|
|
398
1360
|
static async create(properties) {
|
|
399
1361
|
if (!properties.encoding || !properties?.meta?.next) {
|
|
@@ -472,14 +1434,30 @@ let EntryV0 = (() => {
|
|
|
472
1434
|
properties.meta?.gid ||
|
|
473
1435
|
(await EntryV0.createGid(properties.meta?.gidSeed));
|
|
474
1436
|
}
|
|
1437
|
+
const entryType = properties.meta?.type ?? EntryType.APPEND;
|
|
475
1438
|
const metadataEncrypted = await maybeEncrypt(new Meta({
|
|
476
1439
|
clock,
|
|
477
1440
|
gid: gid,
|
|
478
|
-
type:
|
|
1441
|
+
type: entryType,
|
|
479
1442
|
data: properties.meta?.data,
|
|
480
1443
|
next: nextHashes,
|
|
481
1444
|
}), properties.encryption?.keypair, properties.encryption?.receiver.meta);
|
|
482
1445
|
const payload = await maybeEncrypt(payloadToSave, properties.encryption?.keypair, properties.encryption?.receiver.payload);
|
|
1446
|
+
const nativeEncoder = properties.encryption
|
|
1447
|
+
? undefined
|
|
1448
|
+
: await loadNativeEntryV0Encoder();
|
|
1449
|
+
const nativePlainInput = nativeEncoder
|
|
1450
|
+
? {
|
|
1451
|
+
clockId: clock.id,
|
|
1452
|
+
wallTime: clock.timestamp.wallTime,
|
|
1453
|
+
logical: clock.timestamp.logical,
|
|
1454
|
+
gid: gid,
|
|
1455
|
+
next: nextHashes,
|
|
1456
|
+
type: entryType,
|
|
1457
|
+
metaData: properties.meta?.data,
|
|
1458
|
+
payloadData: payloadToSave.data,
|
|
1459
|
+
}
|
|
1460
|
+
: undefined;
|
|
483
1461
|
// Sign id, encrypted payload, clock, nexts, refs
|
|
484
1462
|
const entry = new EntryV0({
|
|
485
1463
|
meta: metadataEncrypted,
|
|
@@ -487,11 +1465,14 @@ let EntryV0 = (() => {
|
|
|
487
1465
|
signatures: undefined,
|
|
488
1466
|
createdLocally: true,
|
|
489
1467
|
});
|
|
490
|
-
const
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
1468
|
+
const signableBytes = nativeEncoder && nativePlainInput
|
|
1469
|
+
? await nativeEncoder.encodeEntryV0Signable(nativePlainInput)
|
|
1470
|
+
: entry.getSignableBytes();
|
|
1471
|
+
let signatures = properties.signers
|
|
1472
|
+
? properties.signers.length === 1
|
|
1473
|
+
? [await properties.signers[0](signableBytes)]
|
|
1474
|
+
: await Promise.all(properties.signers.map((signer) => signer(signableBytes)))
|
|
1475
|
+
: [await properties.identity.sign(signableBytes)];
|
|
495
1476
|
signatures = signatures.sort((a, b) => compare(a.signature, b.signature));
|
|
496
1477
|
const encryptedSignatures = [];
|
|
497
1478
|
const encryptAllSignaturesWithSameKey = isMaybeEryptionPublicKey(properties.encryption?.receiver?.signatures);
|
|
@@ -508,8 +1489,36 @@ let EntryV0 = (() => {
|
|
|
508
1489
|
if (properties.canAppend && !(await properties.canAppend(entry))) {
|
|
509
1490
|
throw new AccessError("Not allowed to append");
|
|
510
1491
|
}
|
|
1492
|
+
let nativeStorage;
|
|
1493
|
+
if (nativeEncoder &&
|
|
1494
|
+
nativePlainInput &&
|
|
1495
|
+
!properties.canAppend &&
|
|
1496
|
+
signatures.length === 1 &&
|
|
1497
|
+
signatures[0].publicKey instanceof Ed25519PublicKey) {
|
|
1498
|
+
const storageInput = {
|
|
1499
|
+
...nativePlainInput,
|
|
1500
|
+
signature: signatures[0].signature,
|
|
1501
|
+
signaturePublicKey: signatures[0].publicKey.publicKey,
|
|
1502
|
+
prehash: signatures[0].prehash,
|
|
1503
|
+
};
|
|
1504
|
+
nativeStorage = nativeEncoder.encodeEntryV0StorageWithCid
|
|
1505
|
+
? await nativeEncoder.encodeEntryV0StorageWithCid(storageInput)
|
|
1506
|
+
: await (async () => {
|
|
1507
|
+
const storageBytes = await nativeEncoder.encodeEntryV0Storage(storageInput);
|
|
1508
|
+
return {
|
|
1509
|
+
bytes: storageBytes,
|
|
1510
|
+
cid: await nativeEncoder.calculateRawCidV1(storageBytes),
|
|
1511
|
+
};
|
|
1512
|
+
})();
|
|
1513
|
+
}
|
|
511
1514
|
// Append hash
|
|
512
|
-
entry.hash =
|
|
1515
|
+
entry.hash = properties.deferStore
|
|
1516
|
+
? nativeStorage
|
|
1517
|
+
? Entry.prepareMultihashBytes(entry, nativeStorage.bytes, nativeStorage.cid)
|
|
1518
|
+
: await Entry.prepareMultihash(entry)
|
|
1519
|
+
: nativeStorage
|
|
1520
|
+
? await Entry.toMultihashBytes(properties.store, entry, nativeStorage.bytes, nativeStorage.cid)
|
|
1521
|
+
: await Entry.toMultihash(properties.store, entry);
|
|
513
1522
|
entry.init({ encoding: properties.encoding });
|
|
514
1523
|
return entry;
|
|
515
1524
|
}
|