@peerbit/shared-log 16.0.12 → 16.0.14
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 +14 -0
- 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 +178 -33
- 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 +17 -15
- package/src/exchange-heads.ts +7 -0
- package/src/index.ts +240 -33
- 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
package/dist/src/index.js
CHANGED
|
@@ -55,7 +55,7 @@ import { CoordinatePersistenceCoordinator, combineCoordinateDeleteHashes, isProm
|
|
|
55
55
|
import { CPUUsageIntervalLag } from "./cpu.js";
|
|
56
56
|
import { debouncedAccumulatorMap, } from "./debounce.js";
|
|
57
57
|
import { CompatibilityModeRetiredError, NativeDurableCommitError, NoPeersError, isNotStartedError, } from "./errors.js";
|
|
58
|
-
import { EXCHANGE_HEADS_REPAIR_HINT, EntryWithRefs, ExchangeHeadsMessage, MAX_RAW_EXCHANGE_MESSAGE_SIZE, RawEntryWithRefs, RawExchangeHeadsMessage, RequestIPrune, RequestIPruneV2, ResponseIPrune, ResponseIPruneV2, SYNC_CAPABILITY_RAW_EXCHANGE_HEADS, SYNC_CAPABILITY_REPLICATION_INFO_V2_APPLY, SYNC_CAPABILITY_REPLICATION_INFO_V2_DECODE, SYNC_CAPABILITY_REPLICATION_INFO_V2_SEND, StashBackedRawExchangeHeadsMessage, SyncCapabilitiesMessage, collectRawExchangeHeadSendPlan, createExchangeHeadsMessages, createRawExchangeHeadsMessages, getExchangeHeadHash, getPreparedRawExchangeGid, getPreparedRawExchangeHashNumber, getPreparedRawExchangeHeadAppendFacts, getPreparedRawExchangeHeadGid, getPreparedRawExchangeHeadRequestedReplicas, getPreparedRawExchangeHeadShallowEntry, getPreparedRawExchangeHeadSignatureVerified, getPreparedRawExchangeNext, getPreparedRawExchangeRequestedReplicas, getPreparedRawExchangeTimestamp, getRawExchangeHeadByteLength, getRawExchangeHeadStashIndexes, initExchangeHeadEntry, isPreparedRawEntryWithRefs, isStashBackedRawExchangeHeadsMessage, materializeVerifiedRawExchangeHeadsMessage, } from "./exchange-heads.js";
|
|
58
|
+
import { EXCHANGE_HEADS_REPAIR_HINT, EntryWithRefs, ExchangeHeadsMessage, MAX_RAW_EXCHANGE_MESSAGE_SIZE, RawEntryWithRefs, RawExchangeHeadsMessage, RequestIPrune, RequestIPruneV2, ResponseIPrune, ResponseIPruneV2, SYNC_CAPABILITY_RAW_EXCHANGE_HEADS, SYNC_CAPABILITY_REPLICATION_INFO_V2_APPLY, SYNC_CAPABILITY_REPLICATION_INFO_V2_CONFIRM, SYNC_CAPABILITY_REPLICATION_INFO_V2_DECODE, SYNC_CAPABILITY_REPLICATION_INFO_V2_SEND, StashBackedRawExchangeHeadsMessage, SyncCapabilitiesMessage, collectRawExchangeHeadSendPlan, createExchangeHeadsMessages, createRawExchangeHeadsMessages, getExchangeHeadHash, getPreparedRawExchangeGid, getPreparedRawExchangeHashNumber, getPreparedRawExchangeHeadAppendFacts, getPreparedRawExchangeHeadGid, getPreparedRawExchangeHeadRequestedReplicas, getPreparedRawExchangeHeadShallowEntry, getPreparedRawExchangeHeadSignatureVerified, getPreparedRawExchangeNext, getPreparedRawExchangeRequestedReplicas, getPreparedRawExchangeTimestamp, getRawExchangeHeadByteLength, getRawExchangeHeadStashIndexes, initExchangeHeadEntry, isPreparedRawEntryWithRefs, isStashBackedRawExchangeHeadsMessage, materializeVerifiedRawExchangeHeadsMessage, } from "./exchange-heads.js";
|
|
59
59
|
import { FanoutEnvelope } from "./fanout-envelope.js";
|
|
60
60
|
import { InstanceLifecycle } from "./instance-lifecycle.js";
|
|
61
61
|
import { MAX_U32, MAX_U64, createNumbers, } from "./integers.js";
|
|
@@ -66,14 +66,15 @@ import { NativeBackboneWriteThroughBlockStore } from "./native-write-through-blo
|
|
|
66
66
|
import { PeerSessionRegistry } from "./peer-session.js";
|
|
67
67
|
import { PIDReplicationController } from "./pid.js";
|
|
68
68
|
import { EntryReplicatedU32, EntryReplicatedU64, ReplicationIntent, ReplicationRangeIndexableU32, ReplicationRangeIndexableU64, ReplicationRangeMessage, appromixateCoverage, calculateCoverage, countCoveringRangesSameOwner, createAssignedRangesQuery, debounceAggregationChanges, getAllMergeCandiates, getCoverSet, getSamples, isEntryReplicated, isMatured, isReplicationRangeMessage, mergeRanges, minimumWidthToCover, shouldAssigneToRangeBoundary as shouldAssignToRangeBoundary, toRebalance, } from "./ranges.js";
|
|
69
|
+
import { receiveSignatureVerificationResult as getReceiveSignatureVerificationResult, withReceiveSignatureVerificationFacts as withSignatureVerificationFacts, } from "./receive-signature-verification.js";
|
|
69
70
|
import { ReplicationAnnouncementCoordinator } from "./replication-announcement.js";
|
|
70
71
|
import { createReplicationDomainHash, } from "./replication-domain-hash.js";
|
|
71
72
|
import { createReplicationDomainTime, } from "./replication-domain-time.js";
|
|
72
73
|
import {} from "./replication-domain.js";
|
|
73
74
|
import { ReplicationInfoV2ReceiveCoordinator } from "./replication-info-v2-receive.js";
|
|
74
|
-
import { ReplicationInfoV2SendCoordinator } from "./replication-info-v2-send.js";
|
|
75
|
+
import { ReplicationInfoV2SendCoordinator, } from "./replication-info-v2-send.js";
|
|
75
76
|
import { classifyReplicationStatus, } from "./replication-status.js";
|
|
76
|
-
import { AbsoluteReplicas, AddedReplicationInfoV2Message, AddedReplicationSegmentMessage, AllReplicatingSegmentsMessage, FullReplicationInfoV2Message, MinReplicas, ReplicationError, ReplicationPingMessage, RequestReplicationInfoMessage, RequestReplicationInfoV2Message, ResponseRoleMessage, StoppedReplicating, StoppedReplicationInfoV2Message, decodeReplicas, encodeReplicas, isReplicationInfoV2Message, maxReplicas, } from "./replication.js";
|
|
77
|
+
import { AbsoluteReplicas, AddedReplicationInfoV2Message, AddedReplicationSegmentMessage, AllReplicatingSegmentsMessage, FullReplicationInfoV2Message, MinReplicas, ReplicationError, ReplicationInfoV2AppliedMessage, ReplicationPingMessage, RequestReplicationInfoMessage, RequestReplicationInfoV2AppliedMessage, RequestReplicationInfoV2Message, ResponseRoleMessage, StoppedReplicating, StoppedReplicationInfoV2Message, decodeReplicas, encodeReplicas, isReplicationInfoV2Message, maxReplicas, } from "./replication.js";
|
|
77
78
|
import { ReplicatorLivenessMonitor } from "./replicator-liveness.js";
|
|
78
79
|
import { createSyncronizer } from "./sync/factory.js";
|
|
79
80
|
import { emitSyncProfileDuration, emitSyncProfileEvent, syncProfileStart, } from "./sync/profile.js";
|
|
@@ -150,11 +151,18 @@ const canUseOptionalNativeModuleImports = () => {
|
|
|
150
151
|
* to avoid doubled slashes.
|
|
151
152
|
*/
|
|
152
153
|
const joinNativeCoordinateDirectory = (nodeDirectory, fsSafeLogId) => `${nodeDirectory.replace(/[/\\]+$/, "")}/coordinates/${fsSafeLogId}`;
|
|
154
|
+
const defaultNativeEntryBlockCompactMaxJournalBytes = 64 * 1024 * 1024;
|
|
153
155
|
const createNativeDurableBlockStore = async (storage) => new AnyBlockStore(await storage.sublevel("blocks", {
|
|
154
|
-
// Strict mirrors remain WAL-backed
|
|
155
|
-
//
|
|
156
|
-
//
|
|
156
|
+
// Strict mirrors remain WAL-backed. On POSIX Node, checkpoint only the
|
|
157
|
+
// historical suffix through the Rust store's fsync + atomic-rename path;
|
|
158
|
+
// browsers/custom backends and Windows retain the prior unbounded WAL until
|
|
159
|
+
// they expose an equally strong directory durability barrier.
|
|
157
160
|
compactOnClose: false,
|
|
161
|
+
...(storage.supportsCrashSafeJournalCheckpoint === true
|
|
162
|
+
? {
|
|
163
|
+
compactMaxJournalBytes: defaultNativeEntryBlockCompactMaxJournalBytes,
|
|
164
|
+
}
|
|
165
|
+
: {}),
|
|
158
166
|
// A native append is acknowledged only after this mirror resolves. The
|
|
159
167
|
// Rust store's normal immutable fast path may resolve before its WAL write;
|
|
160
168
|
// strict mode waits for the journal write and sync, closing the SIGKILL gap.
|
|
@@ -747,6 +755,13 @@ let SharedLog = (() => {
|
|
|
747
755
|
_providerHandle;
|
|
748
756
|
_isTrustedReplicator;
|
|
749
757
|
_logProperties;
|
|
758
|
+
// A successful native signature batch is only an authorization input for the
|
|
759
|
+
// receive operation that requested it. Facts retain the exact verified bytes
|
|
760
|
+
// and are leased around the lower-log join; byte comparison prevents an
|
|
761
|
+
// earlier application callback from mutating a later entry underneath the
|
|
762
|
+
// batch result. The array form also makes overlapping leases for the same
|
|
763
|
+
// object safe without making verification sticky across retries.
|
|
764
|
+
_receiveSignatureVerificationFacts = new WeakMap();
|
|
750
765
|
_closeController;
|
|
751
766
|
_respondToIHaveTimeout;
|
|
752
767
|
_checkedPrune;
|
|
@@ -1815,12 +1830,18 @@ let SharedLog = (() => {
|
|
|
1815
1830
|
this._peerSessions.isReceiveCleanupGateOpen(peerHash),
|
|
1816
1831
|
captureReplicationOwnershipLifecycle: () => this.captureReplicationOwnershipLifecycle(),
|
|
1817
1832
|
isReplicationOwnershipLifecycleActive: (controller) => this.isRepairLifecycleActive(controller),
|
|
1833
|
+
supportsApplicationConfirmation: (peerHash, receiverTransportSession) => this._peerSyncCapabilitySessions.get(peerHash) ===
|
|
1834
|
+
receiverTransportSession &&
|
|
1835
|
+
((this._peerSyncCapabilities.get(peerHash) ?? 0) &
|
|
1836
|
+
SYNC_CAPABILITY_REPLICATION_INFO_V2_CONFIRM) !==
|
|
1837
|
+
0,
|
|
1818
1838
|
});
|
|
1819
1839
|
}
|
|
1820
1840
|
replicationInfoV2ReceiveCapabilities() {
|
|
1821
1841
|
return (SYNC_CAPABILITY_REPLICATION_INFO_V2_DECODE |
|
|
1822
1842
|
SYNC_CAPABILITY_REPLICATION_INFO_V2_SEND |
|
|
1823
1843
|
SYNC_CAPABILITY_REPLICATION_INFO_V2_APPLY |
|
|
1844
|
+
SYNC_CAPABILITY_REPLICATION_INFO_V2_CONFIRM |
|
|
1824
1845
|
(this._logProperties?.sync?.rawExchangeHeads === true
|
|
1825
1846
|
? SYNC_CAPABILITY_RAW_EXCHANGE_HEADS
|
|
1826
1847
|
: 0));
|
|
@@ -3807,7 +3828,11 @@ let SharedLog = (() => {
|
|
|
3807
3828
|
? this.replicationController?.maxMemoryLimit
|
|
3808
3829
|
: undefined;
|
|
3809
3830
|
try {
|
|
3810
|
-
|
|
3831
|
+
const ranges = await this.applyReplicationRole(rangeOrEntry, options);
|
|
3832
|
+
if (options?.confirm) {
|
|
3833
|
+
await this._v2Send.confirmLatest(typeof options.confirm === "object" ? options.confirm : undefined);
|
|
3834
|
+
}
|
|
3835
|
+
return ranges;
|
|
3811
3836
|
}
|
|
3812
3837
|
finally {
|
|
3813
3838
|
const storageObjective = this._isAdaptiveReplicating
|
|
@@ -3900,7 +3925,7 @@ let SharedLog = (() => {
|
|
|
3900
3925
|
this.throwIfReplicationOwnershipLifecycleInactive(replicationOwnershipLifecycleController);
|
|
3901
3926
|
return this._replicate(range, options, replicationOwnershipLifecycleController);
|
|
3902
3927
|
}
|
|
3903
|
-
async unreplicate(rangeOrEntry) {
|
|
3928
|
+
async unreplicate(rangeOrEntry, options) {
|
|
3904
3929
|
const wasAdaptiveReplicating = this._isAdaptiveReplicating;
|
|
3905
3930
|
const previousStorageObjective = wasAdaptiveReplicating
|
|
3906
3931
|
? this.replicationController?.maxMemoryLimit
|
|
@@ -3908,7 +3933,11 @@ let SharedLog = (() => {
|
|
|
3908
3933
|
this.throwIfCheckedPruneRemoveBlocksLocalOperation("replication range mutation");
|
|
3909
3934
|
const replicationOwnershipLifecycleController = this.captureReplicationOwnershipLifecycle();
|
|
3910
3935
|
try {
|
|
3911
|
-
|
|
3936
|
+
const result = await this._unreplicate(rangeOrEntry, replicationOwnershipLifecycleController);
|
|
3937
|
+
if (options?.confirm) {
|
|
3938
|
+
await this._v2Send.confirmLatest(typeof options.confirm === "object" ? options.confirm : undefined);
|
|
3939
|
+
}
|
|
3940
|
+
return result;
|
|
3912
3941
|
}
|
|
3913
3942
|
finally {
|
|
3914
3943
|
const storageObjective = this._isAdaptiveReplicating
|
|
@@ -9436,6 +9465,7 @@ let SharedLog = (() => {
|
|
|
9436
9465
|
: undefined,
|
|
9437
9466
|
};
|
|
9438
9467
|
this._logProperties = options;
|
|
9468
|
+
this._receiveSignatureVerificationFacts = new WeakMap();
|
|
9439
9469
|
this.domain = options?.domain
|
|
9440
9470
|
? options.domain(this)
|
|
9441
9471
|
: createReplicationDomainHash("u64")(this);
|
|
@@ -11302,6 +11332,70 @@ let SharedLog = (() => {
|
|
|
11302
11332
|
}
|
|
11303
11333
|
});
|
|
11304
11334
|
}
|
|
11335
|
+
receiveSignatureVerificationResult(entry) {
|
|
11336
|
+
return getReceiveSignatureVerificationResult(this._receiveSignatureVerificationFacts, entry);
|
|
11337
|
+
}
|
|
11338
|
+
async preverifyReceiveSignaturesBatch(entries, profile) {
|
|
11339
|
+
const candidates = entries.filter((entry) => !entry.createdLocally && !hasPreverifiedSignature(entry));
|
|
11340
|
+
if (candidates.length < NATIVE_ED25519_VERIFY_BATCH_MIN_ENTRIES) {
|
|
11341
|
+
return undefined;
|
|
11342
|
+
}
|
|
11343
|
+
let storageBytes;
|
|
11344
|
+
let signableInputs;
|
|
11345
|
+
try {
|
|
11346
|
+
// Capture the callback-visible storage state and native signable inputs
|
|
11347
|
+
// before the first await so the result is bound to one entry state.
|
|
11348
|
+
storageBytes = candidates.map((entry) => entry.getStorageBytes().slice());
|
|
11349
|
+
signableInputs =
|
|
11350
|
+
this.prepareReceiveNativeEd25519VerificationBatch(candidates);
|
|
11351
|
+
}
|
|
11352
|
+
catch {
|
|
11353
|
+
return undefined;
|
|
11354
|
+
}
|
|
11355
|
+
if (!signableInputs) {
|
|
11356
|
+
return undefined;
|
|
11357
|
+
}
|
|
11358
|
+
const verifyStartedAt = syncProfileStart(profile);
|
|
11359
|
+
let verified;
|
|
11360
|
+
try {
|
|
11361
|
+
verified = await verifyEd25519Batch(signableInputs);
|
|
11362
|
+
}
|
|
11363
|
+
catch {
|
|
11364
|
+
verified = undefined;
|
|
11365
|
+
}
|
|
11366
|
+
if (!verified || verified.length !== candidates.length) {
|
|
11367
|
+
return undefined;
|
|
11368
|
+
}
|
|
11369
|
+
if (profile) {
|
|
11370
|
+
emitSyncProfileDuration(profile, verifyStartedAt, {
|
|
11371
|
+
name: "sharedLog.canAppendBatch.verifySignatures",
|
|
11372
|
+
component: "shared-log",
|
|
11373
|
+
entries: candidates.length,
|
|
11374
|
+
messages: 1,
|
|
11375
|
+
details: {
|
|
11376
|
+
native: true,
|
|
11377
|
+
mode: "signable",
|
|
11378
|
+
programCanAppendDeferred: true,
|
|
11379
|
+
},
|
|
11380
|
+
});
|
|
11381
|
+
}
|
|
11382
|
+
return candidates.map((entry, index) => ({
|
|
11383
|
+
entry,
|
|
11384
|
+
storageBytes: storageBytes[index],
|
|
11385
|
+
verified: verified[index],
|
|
11386
|
+
}));
|
|
11387
|
+
}
|
|
11388
|
+
prepareReceiveNativeEd25519VerificationBatch(entries) {
|
|
11389
|
+
const inputs = this.prepareNativeEd25519VerificationBatch(entries);
|
|
11390
|
+
return inputs?.map((input) => ({
|
|
11391
|
+
signature: input.signature.slice(),
|
|
11392
|
+
publicKey: input.publicKey.slice(),
|
|
11393
|
+
message: input.message.slice(),
|
|
11394
|
+
}));
|
|
11395
|
+
}
|
|
11396
|
+
async withReceiveSignatureVerificationFacts(facts, operation) {
|
|
11397
|
+
return withSignatureVerificationFacts(this._receiveSignatureVerificationFacts, facts, operation);
|
|
11398
|
+
}
|
|
11305
11399
|
async canAppend(entry) {
|
|
11306
11400
|
try {
|
|
11307
11401
|
if (!entry.meta.data) {
|
|
@@ -11313,9 +11407,16 @@ let SharedLog = (() => {
|
|
|
11313
11407
|
return false;
|
|
11314
11408
|
}
|
|
11315
11409
|
checkMinReplicasLimit(replicas);
|
|
11316
|
-
|
|
11410
|
+
const receiveSignatureVerification = this.receiveSignatureVerificationResult(entry);
|
|
11411
|
+
if (receiveSignatureVerification === false) {
|
|
11412
|
+
return false;
|
|
11413
|
+
}
|
|
11414
|
+
// Locally-created entries were signed before append. Raw prepared entries
|
|
11415
|
+
// can carry a durable verifier fact from their decoder; plain receive facts
|
|
11416
|
+
// are scoped to this lower-log join and checked against the exact bytes.
|
|
11317
11417
|
if (!entry.createdLocally &&
|
|
11318
11418
|
!hasPreverifiedSignature(entry) &&
|
|
11419
|
+
receiveSignatureVerification !== true &&
|
|
11319
11420
|
!(await entry.verifySignatures())) {
|
|
11320
11421
|
return false;
|
|
11321
11422
|
}
|
|
@@ -13453,6 +13554,9 @@ let SharedLog = (() => {
|
|
|
13453
13554
|
// entry views.
|
|
13454
13555
|
const programCanAppend = !!this._logProperties?.canAppend;
|
|
13455
13556
|
const programOnChange = !!this._logProperties?.onChange;
|
|
13557
|
+
const receiveSignatureVerificationFacts = programCanAppend
|
|
13558
|
+
? await this.preverifyReceiveSignaturesBatch(materializeAllToMergeEntries(), syncProfile)
|
|
13559
|
+
: undefined;
|
|
13456
13560
|
const nativeBackboneCommitValidation = programCanAppend
|
|
13457
13561
|
? undefined
|
|
13458
13562
|
: this.validatePreparedRawReceiveHeadsMetadataWithNativeBackbone(allToMerge, syncProfile, { decodedReplicaCounts: receiveReplicaCounts });
|
|
@@ -13617,29 +13721,34 @@ let SharedLog = (() => {
|
|
|
13617
13721
|
const joinOnAppendHashes = programOnChange
|
|
13618
13722
|
? undefined
|
|
13619
13723
|
: onAppendHashes;
|
|
13620
|
-
|
|
13621
|
-
|
|
13622
|
-
|
|
13623
|
-
|
|
13624
|
-
|
|
13625
|
-
|
|
13626
|
-
|
|
13627
|
-
|
|
13628
|
-
|
|
13629
|
-
|
|
13630
|
-
|
|
13631
|
-
|
|
13632
|
-
|
|
13633
|
-
|
|
13634
|
-
|
|
13635
|
-
|
|
13636
|
-
|
|
13637
|
-
|
|
13638
|
-
|
|
13639
|
-
|
|
13640
|
-
|
|
13641
|
-
|
|
13642
|
-
|
|
13724
|
+
let joinedPreparedFacts = false;
|
|
13725
|
+
const joinLowerLog = async () => {
|
|
13726
|
+
joinedPreparedFacts =
|
|
13727
|
+
canUsePreparedAppendFacts &&
|
|
13728
|
+
(await trustedLowerLog.joinPreparedAppendFactsBatch(preparedAppendFacts, {
|
|
13729
|
+
__peerbitEntriesAlreadyMissing: true,
|
|
13730
|
+
__peerbitCanAppendAlreadyValidated: true,
|
|
13731
|
+
__peerbitDeferIndexWrite: true,
|
|
13732
|
+
__peerbitOnAppendHashes: joinOnAppendHashes,
|
|
13733
|
+
__peerbitProfile: syncProfile,
|
|
13734
|
+
__peerbitNativePreparedJoinCommit: nativePreparedJoinCommit,
|
|
13735
|
+
__peerbitNativePreparedJoinCommitValidatesPlan: nativePreparedJoinCommitValidatesPlan,
|
|
13736
|
+
__peerbitOnPreparedJoinCommitted: nativePreparedJoinCommit
|
|
13737
|
+
? finishNativePreparedCoordinates
|
|
13738
|
+
: undefined,
|
|
13739
|
+
}));
|
|
13740
|
+
if (!joinedPreparedFacts) {
|
|
13741
|
+
await trustedLowerLog.join(materializeAllToMergeEntries(), {
|
|
13742
|
+
__peerbitBatchIndependent: true,
|
|
13743
|
+
__peerbitEntriesAlreadyMissing: true,
|
|
13744
|
+
__peerbitCanAppendAlreadyValidated: fallbackCanAppendAlreadyValidated,
|
|
13745
|
+
__peerbitDeferIndexWrite: true,
|
|
13746
|
+
__peerbitOnAppendHashes: joinOnAppendHashes,
|
|
13747
|
+
__peerbitProfile: syncProfile,
|
|
13748
|
+
});
|
|
13749
|
+
}
|
|
13750
|
+
};
|
|
13751
|
+
await this.withReceiveSignatureVerificationFacts(receiveSignatureVerificationFacts, joinLowerLog);
|
|
13643
13752
|
// A recursive lower-log join can resolve successfully while declining
|
|
13644
13753
|
// an individual top-level entry (for example, when one of its parents
|
|
13645
13754
|
// is temporarily unavailable). The public Log.join() API intentionally
|
|
@@ -13897,6 +14006,42 @@ let SharedLog = (() => {
|
|
|
13897
14006
|
this.clearRepairFrontierHashes(context.from.hashcode(), msg.hashes);
|
|
13898
14007
|
return;
|
|
13899
14008
|
}
|
|
14009
|
+
else if (msg instanceof RequestReplicationInfoV2AppliedMessage) {
|
|
14010
|
+
if (receiveSession?.phase === "open" &&
|
|
14011
|
+
this._peerSyncCapabilitySessions.get(receiveFromHash) ===
|
|
14012
|
+
context.message.header.session &&
|
|
14013
|
+
((this._peerSyncCapabilities.get(receiveFromHash) ?? 0) &
|
|
14014
|
+
SYNC_CAPABILITY_REPLICATION_INFO_V2_CONFIRM) !==
|
|
14015
|
+
0) {
|
|
14016
|
+
const applied = this._v2Receive.confirmApplied(msg, {
|
|
14017
|
+
from: context.from,
|
|
14018
|
+
peerSession: receiveSession,
|
|
14019
|
+
receiveEpoch: receiveReplicationInfoReceiveEpoch,
|
|
14020
|
+
senderTransportSession: context.message.header.session,
|
|
14021
|
+
});
|
|
14022
|
+
if (applied) {
|
|
14023
|
+
await this.rpc.send(applied, {
|
|
14024
|
+
mode: new SilentDelivery({
|
|
14025
|
+
to: [context.from],
|
|
14026
|
+
redundancy: 1,
|
|
14027
|
+
}),
|
|
14028
|
+
priority: CONVERGENCE_MESSAGE_PRIORITY,
|
|
14029
|
+
signal: AbortSignal.any([
|
|
14030
|
+
this._closeController.signal,
|
|
14031
|
+
lane.ownershipLifecycleController.signal,
|
|
14032
|
+
]),
|
|
14033
|
+
});
|
|
14034
|
+
}
|
|
14035
|
+
}
|
|
14036
|
+
return;
|
|
14037
|
+
}
|
|
14038
|
+
else if (msg instanceof ReplicationInfoV2AppliedMessage) {
|
|
14039
|
+
this._v2Send.acceptApplied(msg, {
|
|
14040
|
+
from: context.from,
|
|
14041
|
+
receiverTransportSession: context.message.header.session,
|
|
14042
|
+
});
|
|
14043
|
+
return;
|
|
14044
|
+
}
|
|
13900
14045
|
else if (isReplicationInfoV2Message(msg)) {
|
|
13901
14046
|
await this.handleReplicationInfoV2Announcement(msg, laneRequestContext, lane);
|
|
13902
14047
|
}
|