@peerbit/shared-log 16.0.11 → 16.0.13
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/src/exchange-heads.d.ts +6 -0
- package/dist/src/exchange-heads.d.ts.map +1 -1
- package/dist/src/exchange-heads.js +6 -0
- package/dist/src/exchange-heads.js.map +1 -1
- package/dist/src/index.d.ts +13 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +168 -30
- package/dist/src/index.js.map +1 -1
- package/dist/src/receive-signature-verification.d.ts +9 -0
- package/dist/src/receive-signature-verification.d.ts.map +1 -0
- package/dist/src/receive-signature-verification.js +54 -0
- package/dist/src/receive-signature-verification.js.map +1 -0
- package/dist/src/replication-info-v2-receive.d.ts +12 -1
- package/dist/src/replication-info-v2-receive.d.ts.map +1 -1
- package/dist/src/replication-info-v2-receive.js +30 -1
- package/dist/src/replication-info-v2-receive.js.map +1 -1
- package/dist/src/replication-info-v2-send.d.ts +61 -1
- package/dist/src/replication-info-v2-send.d.ts.map +1 -1
- package/dist/src/replication-info-v2-send.js +335 -9
- package/dist/src/replication-info-v2-send.js.map +1 -1
- package/dist/src/replication.d.ts +31 -0
- package/dist/src/replication.d.ts.map +1 -1
- package/dist/src/replication.js +115 -0
- package/dist/src/replication.js.map +1 -1
- package/package.json +16 -14
- package/src/exchange-heads.ts +7 -0
- package/src/index.ts +226 -30
- package/src/receive-signature-verification.ts +66 -0
- package/src/replication-info-v2-receive.ts +42 -0
- package/src/replication-info-v2-send.ts +452 -11
- package/src/replication.ts +69 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Entry } from "@peerbit/log";
|
|
2
|
+
import { equals as bytesEqual } from "uint8arrays";
|
|
3
|
+
|
|
4
|
+
export type ReceiveSignatureVerificationFact<T> = {
|
|
5
|
+
entry: Entry<T>;
|
|
6
|
+
storageBytes: Uint8Array;
|
|
7
|
+
verified: boolean;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const receiveSignatureVerificationResult = <T>(
|
|
11
|
+
factsByEntry: WeakMap<Entry<T>, ReceiveSignatureVerificationFact<T>[]>,
|
|
12
|
+
entry: Entry<T>,
|
|
13
|
+
): boolean | undefined => {
|
|
14
|
+
const facts = factsByEntry.get(entry);
|
|
15
|
+
if (!facts || facts.length === 0) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
let storageBytes: Uint8Array;
|
|
19
|
+
try {
|
|
20
|
+
storageBytes = entry.getStorageBytes();
|
|
21
|
+
} catch {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
for (let i = facts.length - 1; i >= 0; i--) {
|
|
25
|
+
const fact = facts[i]!;
|
|
26
|
+
if (bytesEqual(storageBytes, fact.storageBytes)) {
|
|
27
|
+
return fact.verified;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const withReceiveSignatureVerificationFacts = async <T, R>(
|
|
34
|
+
factsByEntry: WeakMap<Entry<T>, ReceiveSignatureVerificationFact<T>[]>,
|
|
35
|
+
facts: ReceiveSignatureVerificationFact<T>[] | undefined,
|
|
36
|
+
operation: () => Promise<R>,
|
|
37
|
+
): Promise<R> => {
|
|
38
|
+
if (!facts || facts.length === 0) {
|
|
39
|
+
return operation();
|
|
40
|
+
}
|
|
41
|
+
for (const fact of facts) {
|
|
42
|
+
const active = factsByEntry.get(fact.entry);
|
|
43
|
+
if (active) {
|
|
44
|
+
active.push(fact);
|
|
45
|
+
} else {
|
|
46
|
+
factsByEntry.set(fact.entry, [fact]);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
return await operation();
|
|
51
|
+
} finally {
|
|
52
|
+
for (const fact of facts) {
|
|
53
|
+
const active = factsByEntry.get(fact.entry);
|
|
54
|
+
if (!active) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const index = active.indexOf(fact);
|
|
58
|
+
if (index >= 0) {
|
|
59
|
+
active.splice(index, 1);
|
|
60
|
+
}
|
|
61
|
+
if (active.length === 0) {
|
|
62
|
+
factsByEntry.delete(fact.entry);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
|
@@ -10,7 +10,9 @@ import {
|
|
|
10
10
|
AddedReplicationSegmentMessage,
|
|
11
11
|
AllReplicatingSegmentsMessage,
|
|
12
12
|
FullReplicationInfoV2Message,
|
|
13
|
+
ReplicationInfoV2AppliedMessage,
|
|
13
14
|
type ReplicationInfoV2Message,
|
|
15
|
+
RequestReplicationInfoV2AppliedMessage,
|
|
14
16
|
RequestReplicationInfoV2Message,
|
|
15
17
|
StoppedReplicating,
|
|
16
18
|
StoppedReplicationInfoV2Message,
|
|
@@ -1250,6 +1252,46 @@ export class ReplicationInfoV2ReceiveCoordinator {
|
|
|
1250
1252
|
return true;
|
|
1251
1253
|
}
|
|
1252
1254
|
|
|
1255
|
+
/**
|
|
1256
|
+
* Answer only after the exact authenticated receive generation has committed
|
|
1257
|
+
* the queried sequence (or a newer one). No pending query is retained: the
|
|
1258
|
+
* sender's bounded retry loop reissues an authoritative snapshot and query.
|
|
1259
|
+
*/
|
|
1260
|
+
confirmApplied(
|
|
1261
|
+
request: RequestReplicationInfoV2AppliedMessage,
|
|
1262
|
+
properties: {
|
|
1263
|
+
from: PublicSignKey;
|
|
1264
|
+
peerSession: object;
|
|
1265
|
+
receiveEpoch: object | null;
|
|
1266
|
+
senderTransportSession: bigint;
|
|
1267
|
+
},
|
|
1268
|
+
): ReplicationInfoV2AppliedMessage | undefined {
|
|
1269
|
+
const state = this._receiveStates.get(properties.from.hashcode());
|
|
1270
|
+
if (
|
|
1271
|
+
!state ||
|
|
1272
|
+
state.peerSession !== properties.peerSession ||
|
|
1273
|
+
state.receiveEpoch !== properties.receiveEpoch ||
|
|
1274
|
+
state.senderTransportSession !== properties.senderTransportSession ||
|
|
1275
|
+
!state.target.equals(properties.from) ||
|
|
1276
|
+
!state.receiverBinding ||
|
|
1277
|
+
!bytesEqual(request.receiverChallenge, state.receiverBinding) ||
|
|
1278
|
+
!state.senderEpoch ||
|
|
1279
|
+
!bytesEqual(request.senderEpoch, state.senderEpoch) ||
|
|
1280
|
+
request.sequence <= 0n ||
|
|
1281
|
+
state.lastSequence === undefined ||
|
|
1282
|
+
state.lastSequence < request.sequence ||
|
|
1283
|
+
!this.isStateCurrent(state)
|
|
1284
|
+
) {
|
|
1285
|
+
return undefined;
|
|
1286
|
+
}
|
|
1287
|
+
return new ReplicationInfoV2AppliedMessage({
|
|
1288
|
+
receiverChallenge: request.receiverChallenge.slice(),
|
|
1289
|
+
senderEpoch: request.senderEpoch.slice(),
|
|
1290
|
+
sequence: request.sequence,
|
|
1291
|
+
revision: request.revision,
|
|
1292
|
+
});
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1253
1295
|
requireFullAfterFailure(
|
|
1254
1296
|
admission: ReplicationInfoV2ReceiveAdmission,
|
|
1255
1297
|
): boolean {
|