@brightchain/brightchain-lib 0.29.27 → 0.30.1
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/package.json +2 -2
- package/src/lib/constants.d.ts +3 -26
- package/src/lib/constants.d.ts.map +1 -1
- package/src/lib/constants.js +2 -1
- package/src/lib/constants.js.map +1 -1
- package/src/lib/db/collection.d.ts +1 -1
- package/src/lib/db/collection.d.ts.map +1 -1
- package/src/lib/db/collection.js +2 -1
- package/src/lib/db/collection.js.map +1 -1
- package/src/lib/enumerations/brightChainStrings.d.ts +18 -0
- package/src/lib/enumerations/brightChainStrings.d.ts.map +1 -1
- package/src/lib/enumerations/brightChainStrings.js +20 -0
- package/src/lib/enumerations/brightChainStrings.js.map +1 -1
- package/src/lib/enumerations/friendRequestStatus.d.ts +7 -0
- package/src/lib/enumerations/friendRequestStatus.d.ts.map +1 -0
- package/src/lib/enumerations/friendRequestStatus.js +11 -0
- package/src/lib/enumerations/friendRequestStatus.js.map +1 -0
- package/src/lib/enumerations/friendsErrorCode.d.ts +10 -0
- package/src/lib/enumerations/friendsErrorCode.d.ts.map +1 -0
- package/src/lib/enumerations/friendsErrorCode.js +14 -0
- package/src/lib/enumerations/friendsErrorCode.js.map +1 -0
- package/src/lib/enumerations/friendshipStatus.d.ts +7 -0
- package/src/lib/enumerations/friendshipStatus.d.ts.map +1 -0
- package/src/lib/enumerations/friendshipStatus.js +11 -0
- package/src/lib/enumerations/friendshipStatus.js.map +1 -0
- package/src/lib/enumerations/index.d.ts +3 -0
- package/src/lib/enumerations/index.d.ts.map +1 -1
- package/src/lib/enumerations/index.js +4 -0
- package/src/lib/enumerations/index.js.map +1 -1
- package/src/lib/errors/friendsServiceError.d.ts +20 -0
- package/src/lib/errors/friendsServiceError.d.ts.map +1 -0
- package/src/lib/errors/friendsServiceError.js +48 -0
- package/src/lib/errors/friendsServiceError.js.map +1 -0
- package/src/lib/errors/index.d.ts +5 -0
- package/src/lib/errors/index.d.ts.map +1 -1
- package/src/lib/errors/index.js +8 -0
- package/src/lib/errors/index.js.map +1 -1
- package/src/lib/i18n/strings/englishUs.d.ts.map +1 -1
- package/src/lib/i18n/strings/englishUs.js +20 -0
- package/src/lib/i18n/strings/englishUs.js.map +1 -1
- package/src/lib/i18n/strings/french.d.ts.map +1 -1
- package/src/lib/i18n/strings/french.js +20 -0
- package/src/lib/i18n/strings/french.js.map +1 -1
- package/src/lib/i18n/strings/german.d.ts.map +1 -1
- package/src/lib/i18n/strings/german.js +20 -0
- package/src/lib/i18n/strings/german.js.map +1 -1
- package/src/lib/i18n/strings/japanese.d.ts.map +1 -1
- package/src/lib/i18n/strings/japanese.js +20 -0
- package/src/lib/i18n/strings/japanese.js.map +1 -1
- package/src/lib/i18n/strings/mandarin.d.ts.map +1 -1
- package/src/lib/i18n/strings/mandarin.js +20 -0
- package/src/lib/i18n/strings/mandarin.js.map +1 -1
- package/src/lib/i18n/strings/spanish.d.ts.map +1 -1
- package/src/lib/i18n/strings/spanish.js +20 -0
- package/src/lib/i18n/strings/spanish.js.map +1 -1
- package/src/lib/i18n/strings/ukrainian.d.ts.map +1 -1
- package/src/lib/i18n/strings/ukrainian.js +20 -0
- package/src/lib/i18n/strings/ukrainian.js.map +1 -1
- package/src/lib/interfaces/appSubsystemPlugin.d.ts +69 -0
- package/src/lib/interfaces/appSubsystemPlugin.d.ts.map +1 -0
- package/src/lib/interfaces/appSubsystemPlugin.js +3 -0
- package/src/lib/interfaces/appSubsystemPlugin.js.map +1 -0
- package/src/lib/interfaces/communication.d.ts +2 -0
- package/src/lib/interfaces/communication.d.ts.map +1 -1
- package/src/lib/interfaces/constants.d.ts +2 -0
- package/src/lib/interfaces/constants.d.ts.map +1 -1
- package/src/lib/interfaces/friends/baseFriendRequest.d.ts +13 -0
- package/src/lib/interfaces/friends/baseFriendRequest.d.ts.map +1 -0
- package/src/lib/interfaces/friends/baseFriendRequest.js +3 -0
- package/src/lib/interfaces/friends/baseFriendRequest.js.map +1 -0
- package/src/lib/interfaces/friends/baseFriendship.d.ts +11 -0
- package/src/lib/interfaces/friends/baseFriendship.d.ts.map +1 -0
- package/src/lib/interfaces/friends/baseFriendship.js +3 -0
- package/src/lib/interfaces/friends/baseFriendship.js.map +1 -0
- package/src/lib/interfaces/friends/friendsService.d.ts +32 -0
- package/src/lib/interfaces/friends/friendsService.d.ts.map +1 -0
- package/src/lib/interfaces/friends/friendsService.js +3 -0
- package/src/lib/interfaces/friends/friendsService.js.map +1 -0
- package/src/lib/interfaces/friends/friendsSuggestionProvider.d.ts +17 -0
- package/src/lib/interfaces/friends/friendsSuggestionProvider.d.ts.map +1 -0
- package/src/lib/interfaces/friends/friendsSuggestionProvider.js +3 -0
- package/src/lib/interfaces/friends/friendsSuggestionProvider.js.map +1 -0
- package/src/lib/interfaces/friends/index.d.ts +6 -0
- package/src/lib/interfaces/friends/index.d.ts.map +1 -0
- package/src/lib/interfaces/friends/index.js +3 -0
- package/src/lib/interfaces/friends/index.js.map +1 -0
- package/src/lib/interfaces/friends/pagination.d.ts +11 -0
- package/src/lib/interfaces/friends/pagination.d.ts.map +1 -0
- package/src/lib/interfaces/friends/pagination.js +3 -0
- package/src/lib/interfaces/friends/pagination.js.map +1 -0
- package/src/lib/interfaces/index.d.ts +2 -0
- package/src/lib/interfaces/index.d.ts.map +1 -1
- package/src/lib/interfaces/storage/documentTypes.d.ts +4 -0
- package/src/lib/interfaces/storage/documentTypes.d.ts.map +1 -1
- package/src/lib/services/communication/channelService.d.ts +16 -2
- package/src/lib/services/communication/channelService.d.ts.map +1 -1
- package/src/lib/services/communication/channelService.js +78 -13
- package/src/lib/services/communication/channelService.js.map +1 -1
- package/src/lib/services/communication/conversationService.d.ts.map +1 -1
- package/src/lib/services/communication/conversationService.js +32 -2
- package/src/lib/services/communication/conversationService.js.map +1 -1
- package/src/lib/services/communication/groupService.d.ts.map +1 -1
- package/src/lib/services/communication/groupService.js +28 -2
- package/src/lib/services/communication/groupService.js.map +1 -1
- package/src/lib/services/communication/serverService.js +4 -6
- package/src/lib/services/communication/serverService.js.map +1 -1
- package/src/lib/services/copyOnWrite.service.d.ts +110 -0
- package/src/lib/services/copyOnWrite.service.d.ts.map +1 -0
- package/src/lib/services/copyOnWrite.service.js +256 -0
- package/src/lib/services/copyOnWrite.service.js.map +1 -0
- package/src/lib/services/index.d.ts +1 -0
- package/src/lib/services/index.d.ts.map +1 -1
- package/src/lib/services/index.js +1 -0
- package/src/lib/services/index.js.map +1 -1
- package/src/lib/services/memberStore.d.ts +7 -1
- package/src/lib/services/memberStore.d.ts.map +1 -1
- package/src/lib/services/memberStore.js +57 -1
- package/src/lib/services/memberStore.js.map +1 -1
- package/src/lib/utils/index.d.ts +6 -0
- package/src/lib/utils/index.d.ts.map +1 -1
- package/src/lib/utils/index.js +9 -0
- package/src/lib/utils/index.js.map +1 -1
- package/src/lib/utils/sortPair.d.ts +6 -0
- package/src/lib/utils/sortPair.d.ts.map +1 -0
- package/src/lib/utils/sortPair.js +11 -0
- package/src/lib/utils/sortPair.js.map +1 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { Member, type PlatformID } from '@digitaldefiance/ecies-lib';
|
|
2
|
+
import { ConstituentBlockListBlock } from '../blocks/cbl';
|
|
3
|
+
import { ExtendedCBL } from '../blocks/extendedCbl';
|
|
4
|
+
import { InMemoryBlockTuple } from '../blocks/memoryTuple';
|
|
5
|
+
import { RandomBlock } from '../blocks/random';
|
|
6
|
+
import { WhitenedBlock } from '../blocks/whitened';
|
|
7
|
+
import { BlockSize } from '../enumerations/blockSize';
|
|
8
|
+
import { Checksum } from '../types/checksum';
|
|
9
|
+
import type { CBLService } from './cblService';
|
|
10
|
+
import type { ChecksumService } from './checksum.service';
|
|
11
|
+
/**
|
|
12
|
+
* Result of a CopyOnWrite operation.
|
|
13
|
+
* Contains the new CBL and metadata about what changed.
|
|
14
|
+
*/
|
|
15
|
+
export interface CopyOnWriteResult<TID extends PlatformID = Uint8Array> {
|
|
16
|
+
/** The new CBL referencing both reused and new blocks */
|
|
17
|
+
cbl: ConstituentBlockListBlock<TID> | ExtendedCBL<TID>;
|
|
18
|
+
/** Number of tuples reused from the original CBL */
|
|
19
|
+
reusedTupleCount: number;
|
|
20
|
+
/** Number of new tuples created for changed data */
|
|
21
|
+
newTupleCount: number;
|
|
22
|
+
/** Total number of tuples in the new CBL */
|
|
23
|
+
totalTupleCount: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Options for the CopyOnWrite operation.
|
|
27
|
+
*/
|
|
28
|
+
export interface CopyOnWriteOptions {
|
|
29
|
+
/** If true, create an ExtendedCBL with file metadata */
|
|
30
|
+
createExtendedCbl?: boolean;
|
|
31
|
+
/** File name for ExtendedCBL */
|
|
32
|
+
fileName?: string;
|
|
33
|
+
/** MIME type for ExtendedCBL */
|
|
34
|
+
mimeType?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* CopyOnWriteService provides efficient versioning for CBL-based data.
|
|
38
|
+
*
|
|
39
|
+
* When data changes, instead of re-creating all blocks from scratch, this service:
|
|
40
|
+
* 1. Reads the new data in block-sized chunks
|
|
41
|
+
* 2. Compares each chunk against the corresponding original block data
|
|
42
|
+
* (recovered by XORing the tuple's constituent blocks)
|
|
43
|
+
* 3. Reuses the original tuple addresses for unchanged blocks
|
|
44
|
+
* 4. Creates new tuples only for blocks whose data has changed
|
|
45
|
+
* 5. Produces a new CBL that references both old (reused) and new block addresses
|
|
46
|
+
*
|
|
47
|
+
* This is analogous to copy-on-write in operating systems: we share unchanged
|
|
48
|
+
* pages and only allocate new storage for modified pages.
|
|
49
|
+
*
|
|
50
|
+
* The tuple size (typically 3) means each "logical block" in the CBL is
|
|
51
|
+
* represented by `tupleSize` addresses. When we say "reuse a tuple," we
|
|
52
|
+
* mean we copy all `tupleSize` addresses from the old CBL into the new one.
|
|
53
|
+
*
|
|
54
|
+
* @typeParam TID - The platform ID type (defaults to Uint8Array)
|
|
55
|
+
*/
|
|
56
|
+
export declare class CopyOnWriteService<TID extends PlatformID = Uint8Array> {
|
|
57
|
+
private readonly checksumService;
|
|
58
|
+
private readonly cblService;
|
|
59
|
+
constructor(checksumService?: ChecksumService, cblService?: CBLService<TID>);
|
|
60
|
+
/**
|
|
61
|
+
* Create a new version of a CBL by applying changes from new data,
|
|
62
|
+
* reusing unchanged blocks from the original CBL.
|
|
63
|
+
*
|
|
64
|
+
* @param originalCbl - The existing CBL to base the new version on
|
|
65
|
+
* @param newData - The complete new data as a Uint8Array
|
|
66
|
+
* @param creator - The member creating the new version
|
|
67
|
+
* @param blockSize - The block size to use (must match the original CBL's block size)
|
|
68
|
+
* @param getBlockData - Function to retrieve raw block data by checksum from the store
|
|
69
|
+
* @param whitenedBlockSource - Function to get whitened blocks for new tuples
|
|
70
|
+
* @param randomBlockSource - Function to get random blocks for new tuples
|
|
71
|
+
* @param persistTuple - Function to persist newly created tuples
|
|
72
|
+
* @param options - Optional settings for extended CBL creation
|
|
73
|
+
* @returns The new CBL and statistics about reuse
|
|
74
|
+
*/
|
|
75
|
+
newVersion(originalCbl: ConstituentBlockListBlock<TID>, newData: Uint8Array, creator: Member<TID>, blockSize: BlockSize, getBlockData: (checksum: Checksum) => Promise<Uint8Array>, whitenedBlockSource: () => WhitenedBlock | undefined, randomBlockSource: () => RandomBlock, persistTuple: (tuple: InMemoryBlockTuple) => Promise<void>, options?: CopyOnWriteOptions): Promise<CopyOnWriteResult<TID>>;
|
|
76
|
+
/**
|
|
77
|
+
* Recover the original plaintext data from a tuple by XORing all
|
|
78
|
+
* constituent blocks together.
|
|
79
|
+
*
|
|
80
|
+
* In the OFF system, a tuple of `tupleSize` blocks is stored such that
|
|
81
|
+
* XORing all blocks together recovers the original data:
|
|
82
|
+
* plaintext = block[0] XOR block[1] XOR ... XOR block[tupleSize-1]
|
|
83
|
+
*
|
|
84
|
+
* @param tupleAddresses - The checksums of the blocks in the tuple
|
|
85
|
+
* @param getBlockData - Function to retrieve raw block data by checksum
|
|
86
|
+
* @returns The recovered plaintext data
|
|
87
|
+
*/
|
|
88
|
+
private recoverTupleData;
|
|
89
|
+
/**
|
|
90
|
+
* Compare two block-sized byte arrays for equality.
|
|
91
|
+
* Uses constant-length comparison (always checks all bytes).
|
|
92
|
+
*/
|
|
93
|
+
private blocksEqual;
|
|
94
|
+
/**
|
|
95
|
+
* Create a new tuple for a data block by XORing it with whitener/random blocks,
|
|
96
|
+
* then persist the tuple.
|
|
97
|
+
*
|
|
98
|
+
* @returns The checksums of all blocks in the new tuple (in order)
|
|
99
|
+
*/
|
|
100
|
+
private createNewTuple;
|
|
101
|
+
/**
|
|
102
|
+
* Convert an array of Checksums to a concatenated Uint8Array buffer.
|
|
103
|
+
*/
|
|
104
|
+
private addressesToBuffer;
|
|
105
|
+
/**
|
|
106
|
+
* Helper to convert a Readable stream to Uint8Array.
|
|
107
|
+
*/
|
|
108
|
+
private streamToUint8Array;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=copyOnWrite.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copyOnWrite.service.d.ts","sourceRoot":"","sources":["../../../../../brightchain-lib/src/lib/services/copyOnWrite.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAInD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG1D;;;GAGG;AACH,MAAM,WAAW,iBAAiB,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU;IACpE,yDAAyD;IACzD,GAAG,EAAE,yBAAyB,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IACvD,oDAAoD;IACpD,gBAAgB,EAAE,MAAM,CAAC;IACzB,oDAAoD;IACpD,aAAa,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,kBAAkB,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU;IACjE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAClD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAkB;gBAG3C,eAAe,CAAC,EAAE,eAAe,EACjC,UAAU,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC;IAQ9B;;;;;;;;;;;;;;OAcG;IACU,UAAU,CACrB,WAAW,EAAE,yBAAyB,CAAC,GAAG,CAAC,EAC3C,OAAO,EAAE,UAAU,EACnB,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,EACpB,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,UAAU,CAAC,EACzD,mBAAmB,EAAE,MAAM,aAAa,GAAG,SAAS,EACpD,iBAAiB,EAAE,MAAM,WAAW,EACpC,YAAY,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,EAC1D,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;IA0HlC;;;;;;;;;;;OAWG;YACW,gBAAgB;IA2B9B;;;OAGG;IACH,OAAO,CAAC,WAAW;IAgBnB;;;;;OAKG;YACW,cAAc;IAkD5B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAYzB;;OAEG;YACW,kBAAkB;CAcjC"}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CopyOnWriteService = void 0;
|
|
4
|
+
const cbl_1 = require("../blocks/cbl");
|
|
5
|
+
const extendedCbl_1 = require("../blocks/extendedCbl");
|
|
6
|
+
const memoryTuple_1 = require("../blocks/memoryTuple");
|
|
7
|
+
const rawData_1 = require("../blocks/rawData");
|
|
8
|
+
const constants_1 = require("../constants");
|
|
9
|
+
const blockEncryptionType_1 = require("../enumerations/blockEncryptionType");
|
|
10
|
+
const globalServiceProvider_1 = require("./globalServiceProvider");
|
|
11
|
+
/**
|
|
12
|
+
* CopyOnWriteService provides efficient versioning for CBL-based data.
|
|
13
|
+
*
|
|
14
|
+
* When data changes, instead of re-creating all blocks from scratch, this service:
|
|
15
|
+
* 1. Reads the new data in block-sized chunks
|
|
16
|
+
* 2. Compares each chunk against the corresponding original block data
|
|
17
|
+
* (recovered by XORing the tuple's constituent blocks)
|
|
18
|
+
* 3. Reuses the original tuple addresses for unchanged blocks
|
|
19
|
+
* 4. Creates new tuples only for blocks whose data has changed
|
|
20
|
+
* 5. Produces a new CBL that references both old (reused) and new block addresses
|
|
21
|
+
*
|
|
22
|
+
* This is analogous to copy-on-write in operating systems: we share unchanged
|
|
23
|
+
* pages and only allocate new storage for modified pages.
|
|
24
|
+
*
|
|
25
|
+
* The tuple size (typically 3) means each "logical block" in the CBL is
|
|
26
|
+
* represented by `tupleSize` addresses. When we say "reuse a tuple," we
|
|
27
|
+
* mean we copy all `tupleSize` addresses from the old CBL into the new one.
|
|
28
|
+
*
|
|
29
|
+
* @typeParam TID - The platform ID type (defaults to Uint8Array)
|
|
30
|
+
*/
|
|
31
|
+
class CopyOnWriteService {
|
|
32
|
+
checksumService;
|
|
33
|
+
cblService;
|
|
34
|
+
constructor(checksumService, cblService) {
|
|
35
|
+
this.checksumService =
|
|
36
|
+
checksumService ?? (0, globalServiceProvider_1.getGlobalServiceProvider)().checksumService;
|
|
37
|
+
this.cblService =
|
|
38
|
+
cblService ?? (0, globalServiceProvider_1.getGlobalServiceProvider)().cblService;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Create a new version of a CBL by applying changes from new data,
|
|
42
|
+
* reusing unchanged blocks from the original CBL.
|
|
43
|
+
*
|
|
44
|
+
* @param originalCbl - The existing CBL to base the new version on
|
|
45
|
+
* @param newData - The complete new data as a Uint8Array
|
|
46
|
+
* @param creator - The member creating the new version
|
|
47
|
+
* @param blockSize - The block size to use (must match the original CBL's block size)
|
|
48
|
+
* @param getBlockData - Function to retrieve raw block data by checksum from the store
|
|
49
|
+
* @param whitenedBlockSource - Function to get whitened blocks for new tuples
|
|
50
|
+
* @param randomBlockSource - Function to get random blocks for new tuples
|
|
51
|
+
* @param persistTuple - Function to persist newly created tuples
|
|
52
|
+
* @param options - Optional settings for extended CBL creation
|
|
53
|
+
* @returns The new CBL and statistics about reuse
|
|
54
|
+
*/
|
|
55
|
+
async newVersion(originalCbl, newData, creator, blockSize, getBlockData, whitenedBlockSource, randomBlockSource, persistTuple, options) {
|
|
56
|
+
const now = new Date();
|
|
57
|
+
const tupleSize = originalCbl.tupleSize;
|
|
58
|
+
const originalAddresses = originalCbl.addresses;
|
|
59
|
+
const blockSizeBytes = blockSize;
|
|
60
|
+
// Calculate how many logical blocks (tuples) the original CBL has
|
|
61
|
+
const originalTupleCount = Math.floor(originalAddresses.length / tupleSize);
|
|
62
|
+
// Calculate how many logical blocks the new data needs
|
|
63
|
+
const newTotalBlocks = Math.ceil(newData.length / blockSizeBytes);
|
|
64
|
+
// We'll build the new address list tuple by tuple
|
|
65
|
+
const newAddressList = [];
|
|
66
|
+
let reusedTupleCount = 0;
|
|
67
|
+
let newTupleCount = 0;
|
|
68
|
+
for (let tupleIndex = 0; tupleIndex < newTotalBlocks; tupleIndex++) {
|
|
69
|
+
// Extract the new data chunk for this block position
|
|
70
|
+
const chunkStart = tupleIndex * blockSizeBytes;
|
|
71
|
+
const chunkEnd = Math.min(chunkStart + blockSizeBytes, newData.length);
|
|
72
|
+
let newChunk = newData.slice(chunkStart, chunkEnd);
|
|
73
|
+
// Pad the last chunk if needed
|
|
74
|
+
if (newChunk.length < blockSizeBytes) {
|
|
75
|
+
const padded = new Uint8Array(blockSizeBytes);
|
|
76
|
+
padded.set(newChunk);
|
|
77
|
+
// Remaining bytes are zero-filled (deterministic padding for comparison)
|
|
78
|
+
newChunk = padded;
|
|
79
|
+
}
|
|
80
|
+
// Check if we can reuse the original tuple at this position
|
|
81
|
+
let reused = false;
|
|
82
|
+
if (tupleIndex < originalTupleCount) {
|
|
83
|
+
const originalTupleStart = tupleIndex * tupleSize;
|
|
84
|
+
const originalTupleAddresses = originalAddresses.slice(originalTupleStart, originalTupleStart + tupleSize);
|
|
85
|
+
// Recover the original plaintext by XORing all blocks in the tuple
|
|
86
|
+
try {
|
|
87
|
+
const originalPlaintext = await this.recoverTupleData(originalTupleAddresses, getBlockData);
|
|
88
|
+
// Compare: if the data is identical, reuse the old addresses
|
|
89
|
+
if (this.blocksEqual(newChunk, originalPlaintext)) {
|
|
90
|
+
for (const addr of originalTupleAddresses) {
|
|
91
|
+
newAddressList.push(addr);
|
|
92
|
+
}
|
|
93
|
+
reusedTupleCount++;
|
|
94
|
+
reused = true;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// If we can't recover the original data (block missing, etc.),
|
|
99
|
+
// fall through to create a new tuple
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (!reused) {
|
|
103
|
+
// Create a new tuple for this changed block
|
|
104
|
+
const tupleAddresses = await this.createNewTuple(newChunk, blockSize, creator, whitenedBlockSource, randomBlockSource, persistTuple, now);
|
|
105
|
+
for (const addr of tupleAddresses) {
|
|
106
|
+
newAddressList.push(addr);
|
|
107
|
+
}
|
|
108
|
+
newTupleCount++;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Build the address list buffer
|
|
112
|
+
const addressListBuffer = this.addressesToBuffer(newAddressList);
|
|
113
|
+
// Create the new CBL header
|
|
114
|
+
const isExtended = options?.createExtendedCbl && options.fileName;
|
|
115
|
+
const extendedInfo = isExtended
|
|
116
|
+
? {
|
|
117
|
+
fileName: options.fileName,
|
|
118
|
+
mimeType: options?.mimeType ?? 'application/octet-stream',
|
|
119
|
+
}
|
|
120
|
+
: undefined;
|
|
121
|
+
const { headerData } = this.cblService.makeCblHeader(creator, now, newAddressList.length, newData.length, addressListBuffer, blockSize, blockEncryptionType_1.BlockEncryptionType.None, extendedInfo, tupleSize);
|
|
122
|
+
// Assemble the full CBL data: header + address list
|
|
123
|
+
const cblData = new Uint8Array(headerData.length + addressListBuffer.length);
|
|
124
|
+
cblData.set(headerData, 0);
|
|
125
|
+
cblData.set(addressListBuffer, headerData.length);
|
|
126
|
+
// Create the CBL block
|
|
127
|
+
const cbl = isExtended
|
|
128
|
+
? new extendedCbl_1.ExtendedCBL(cblData, creator, blockSize)
|
|
129
|
+
: new cbl_1.ConstituentBlockListBlock(cblData, creator, blockSize);
|
|
130
|
+
return {
|
|
131
|
+
cbl,
|
|
132
|
+
reusedTupleCount,
|
|
133
|
+
newTupleCount,
|
|
134
|
+
totalTupleCount: reusedTupleCount + newTupleCount,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Recover the original plaintext data from a tuple by XORing all
|
|
139
|
+
* constituent blocks together.
|
|
140
|
+
*
|
|
141
|
+
* In the OFF system, a tuple of `tupleSize` blocks is stored such that
|
|
142
|
+
* XORing all blocks together recovers the original data:
|
|
143
|
+
* plaintext = block[0] XOR block[1] XOR ... XOR block[tupleSize-1]
|
|
144
|
+
*
|
|
145
|
+
* @param tupleAddresses - The checksums of the blocks in the tuple
|
|
146
|
+
* @param getBlockData - Function to retrieve raw block data by checksum
|
|
147
|
+
* @returns The recovered plaintext data
|
|
148
|
+
*/
|
|
149
|
+
async recoverTupleData(tupleAddresses, getBlockData) {
|
|
150
|
+
if (tupleAddresses.length === 0) {
|
|
151
|
+
throw new Error('Cannot recover data from empty tuple');
|
|
152
|
+
}
|
|
153
|
+
// Load all blocks in the tuple
|
|
154
|
+
const blockDataArrays = await Promise.all(tupleAddresses.map((addr) => getBlockData(addr)));
|
|
155
|
+
// XOR all blocks together to recover the plaintext
|
|
156
|
+
const result = new Uint8Array(blockDataArrays[0].length);
|
|
157
|
+
result.set(blockDataArrays[0]);
|
|
158
|
+
for (let i = 1; i < blockDataArrays.length; i++) {
|
|
159
|
+
const current = blockDataArrays[i];
|
|
160
|
+
for (let j = 0; j < result.length; j++) {
|
|
161
|
+
result[j] ^= current[j];
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Compare two block-sized byte arrays for equality.
|
|
168
|
+
* Uses constant-length comparison (always checks all bytes).
|
|
169
|
+
*/
|
|
170
|
+
blocksEqual(a, b) {
|
|
171
|
+
if (a.length !== b.length) {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
let equal = true;
|
|
175
|
+
for (let i = 0; i < a.length; i++) {
|
|
176
|
+
if (a[i] !== b[i]) {
|
|
177
|
+
equal = false;
|
|
178
|
+
// Don't break early — we compare all bytes for consistency,
|
|
179
|
+
// though this isn't a security-sensitive comparison
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return equal;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Create a new tuple for a data block by XORing it with whitener/random blocks,
|
|
187
|
+
* then persist the tuple.
|
|
188
|
+
*
|
|
189
|
+
* @returns The checksums of all blocks in the new tuple (in order)
|
|
190
|
+
*/
|
|
191
|
+
async createNewTuple(data, blockSize, creator, whitenedBlockSource, randomBlockSource, persistTuple, dateCreated) {
|
|
192
|
+
// Gather whitener/random blocks for the tuple (tupleSize - 1 blocks)
|
|
193
|
+
const companions = [];
|
|
194
|
+
for (let i = 0; i < constants_1.TUPLE.SIZE - 1; i++) {
|
|
195
|
+
const whitened = whitenedBlockSource();
|
|
196
|
+
if (whitened) {
|
|
197
|
+
companions.push(whitened);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
companions.push(randomBlockSource());
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// XOR the data with all companion blocks to produce the "prime" block
|
|
204
|
+
let xored = new Uint8Array(data);
|
|
205
|
+
for (const companion of companions) {
|
|
206
|
+
const companionData = companion.data instanceof Uint8Array
|
|
207
|
+
? companion.data
|
|
208
|
+
: await this.streamToUint8Array(companion.data);
|
|
209
|
+
for (let j = 0; j < xored.length; j++) {
|
|
210
|
+
xored[j] ^= companionData[j];
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// Create the prime (XORed result) block
|
|
214
|
+
const primeChecksum = this.checksumService.calculateChecksum(xored);
|
|
215
|
+
const primeBlock = new rawData_1.RawDataBlock(blockSize, xored, dateCreated, primeChecksum);
|
|
216
|
+
// Build the tuple: [prime, ...companions]
|
|
217
|
+
const allBlocks = [primeBlock, ...companions];
|
|
218
|
+
const tuple = new memoryTuple_1.InMemoryBlockTuple(allBlocks);
|
|
219
|
+
await persistTuple(tuple);
|
|
220
|
+
// Return all block checksums in tuple order
|
|
221
|
+
return allBlocks.map((block) => block.idChecksum);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Convert an array of Checksums to a concatenated Uint8Array buffer.
|
|
225
|
+
*/
|
|
226
|
+
addressesToBuffer(addresses) {
|
|
227
|
+
const buffers = addresses.map((addr) => addr.toUint8Array());
|
|
228
|
+
const totalLength = buffers.reduce((sum, buf) => sum + buf.length, 0);
|
|
229
|
+
const result = new Uint8Array(totalLength);
|
|
230
|
+
let offset = 0;
|
|
231
|
+
for (const buf of buffers) {
|
|
232
|
+
result.set(buf, offset);
|
|
233
|
+
offset += buf.length;
|
|
234
|
+
}
|
|
235
|
+
return result;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Helper to convert a Readable stream to Uint8Array.
|
|
239
|
+
*/
|
|
240
|
+
async streamToUint8Array(readable) {
|
|
241
|
+
const chunks = [];
|
|
242
|
+
for await (const chunk of readable) {
|
|
243
|
+
chunks.push(new Uint8Array(chunk));
|
|
244
|
+
}
|
|
245
|
+
const totalLength = chunks.reduce((sum, c) => sum + c.length, 0);
|
|
246
|
+
const result = new Uint8Array(totalLength);
|
|
247
|
+
let offset = 0;
|
|
248
|
+
for (const chunk of chunks) {
|
|
249
|
+
result.set(chunk, offset);
|
|
250
|
+
offset += chunk.length;
|
|
251
|
+
}
|
|
252
|
+
return result;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
exports.CopyOnWriteService = CopyOnWriteService;
|
|
256
|
+
//# sourceMappingURL=copyOnWrite.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copyOnWrite.service.js","sourceRoot":"","sources":["../../../../../brightchain-lib/src/lib/services/copyOnWrite.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@ export * from './brightTrustService';
|
|
|
7
7
|
export * from './brightTrustStateMachine';
|
|
8
8
|
export * from './cblService';
|
|
9
9
|
export * from './checksum.service';
|
|
10
|
+
export * from './copyOnWrite.service';
|
|
10
11
|
export * from './crypto';
|
|
11
12
|
export * from './fec.service';
|
|
12
13
|
export * from './identitySealingPipeline';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../brightchain-lib/src/lib/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,UAAU,CAAC;AACzB,cAAc,0BAA0B,CAAC;AACzC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,OAAO,CAAC;AAGtB,cAAc,cAAc,CAAC;AAG7B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../brightchain-lib/src/lib/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,UAAU,CAAC;AACzB,cAAc,0BAA0B,CAAC;AACzC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,OAAO,CAAC;AAGtB,cAAc,cAAc,CAAC;AAG7B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,YAAY,CAAC"}
|
|
@@ -10,6 +10,7 @@ tslib_1.__exportStar(require("./brightTrustService"), exports);
|
|
|
10
10
|
tslib_1.__exportStar(require("./brightTrustStateMachine"), exports);
|
|
11
11
|
tslib_1.__exportStar(require("./cblService"), exports);
|
|
12
12
|
tslib_1.__exportStar(require("./checksum.service"), exports);
|
|
13
|
+
tslib_1.__exportStar(require("./copyOnWrite.service"), exports);
|
|
13
14
|
tslib_1.__exportStar(require("./crypto"), exports);
|
|
14
15
|
tslib_1.__exportStar(require("./fec.service"), exports);
|
|
15
16
|
tslib_1.__exportStar(require("./identitySealingPipeline"), exports);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../brightchain-lib/src/lib/services/index.ts"],"names":[],"mappings":";;;AAAA,0DAAgC;AAChC,4DAAkC;AAClC,kEAAwC;AACxC,+DAAqC;AACrC,yDAA+B;AAC/B,+DAAqC;AACrC,oEAA0C;AAC1C,uDAA6B;AAC7B,6DAAmC;AACnC,mDAAyB;AACzB,wDAA8B;AAC9B,oEAA0C;AAC1C,8DAAoC;AACpC,mDAAyB;AACzB,mEAAyC;AACzC,wDAA8B;AAC9B,sDAA4B;AAC5B,4DAAkC;AAClC,6DAAmC;AACnC,2DAAiC;AACjC,8DAAoC;AACpC,0DAAgC;AAChC,gEAAsC;AACtC,wDAA8B;AAC9B,gDAAsB;AAEtB,4CAA4C;AAC5C,uDAA6B;AAE7B,8DAA8D;AAC9D,0DAAgC;AAEhC,6DAA6D;AAC7D,qDAA2B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../brightchain-lib/src/lib/services/index.ts"],"names":[],"mappings":";;;AAAA,0DAAgC;AAChC,4DAAkC;AAClC,kEAAwC;AACxC,+DAAqC;AACrC,yDAA+B;AAC/B,+DAAqC;AACrC,oEAA0C;AAC1C,uDAA6B;AAC7B,6DAAmC;AACnC,gEAAsC;AACtC,mDAAyB;AACzB,wDAA8B;AAC9B,oEAA0C;AAC1C,8DAAoC;AACpC,mDAAyB;AACzB,mEAAyC;AACzC,wDAA8B;AAC9B,sDAA4B;AAC5B,4DAAkC;AAClC,6DAAmC;AACnC,2DAAiC;AACjC,8DAAoC;AACpC,0DAAgC;AAChC,gEAAsC;AACtC,wDAA8B;AAC9B,gDAAsB;AAEtB,4CAA4C;AAC5C,uDAA6B;AAE7B,8DAA8D;AAC9D,0DAAgC;AAEhC,6DAA6D;AAC7D,qDAA2B"}
|
|
@@ -109,7 +109,13 @@ export declare class MemberStore<TID extends PlatformID = Uint8Array> implements
|
|
|
109
109
|
*/
|
|
110
110
|
deleteMember(id: TID): Promise<void>;
|
|
111
111
|
/**
|
|
112
|
-
* Update the member index
|
|
112
|
+
* Update the member index.
|
|
113
|
+
*
|
|
114
|
+
* Updates the in-memory indexes AND persists the entry to the
|
|
115
|
+
* `member_index` BrightDb collection (when `_db` is available) so that
|
|
116
|
+
* the data survives server restarts. Without this DB write, members
|
|
117
|
+
* created via `createMember()` / `register()` only existed in memory
|
|
118
|
+
* and were lost on restart.
|
|
113
119
|
*/
|
|
114
120
|
updateIndex(entry: IMemberIndexEntry<TID>): Promise<void>;
|
|
115
121
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memberStore.d.ts","sourceRoot":"","sources":["../../../../../brightchain-lib/src/lib/services/memberStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,MAAM,EACN,UAAU,EACV,YAAY,EAEb,MAAM,4BAA4B,CAAC;AAmBpC,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACf,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,iCAAiC,EAEjC,gCAAgC,EAEjC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAKrE;;GAEG;AACH,qBAAa,WAAW,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU,CAC1D,YAAW,YAAY,CAAC,GAAG,CAAC;IAE5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAc;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAsC;IAClE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA2B;IACvD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IACjD,wEAAwE;IACxE,OAAO,CAAC,GAAG,CAAwB;IAEnC;;;;;;;;OAQG;IACH,OAAO,CAAC,SAAS;gBAoBL,UAAU,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,cAAc;IASxD;;;;;;;;OAQG;IACH,OAAO,CAAC,gBAAgB;IAYxB;;;;OAIG;IACI,KAAK,CAAC,EAAE,EAAE,cAAc,GAAG,IAAI;IAItC;;;;;;;;OAQG;YACW,yBAAyB;IA6DvC;;OAEG;IACU,YAAY,CACvB,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC;QAAE,SAAS,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC;QAAC,QAAQ,EAAE,YAAY,CAAA;KAAE,CAAC;IAyVxE;;;;;;;;OAQG;IACU,SAAS,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAwErD;;;;;;;;;OASG;IACU,qBAAqB,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"memberStore.d.ts","sourceRoot":"","sources":["../../../../../brightchain-lib/src/lib/services/memberStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,MAAM,EACN,UAAU,EACV,YAAY,EAEb,MAAM,4BAA4B,CAAC;AAmBpC,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACf,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,iCAAiC,EAEjC,gCAAgC,EAEjC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAKrE;;GAEG;AACH,qBAAa,WAAW,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU,CAC1D,YAAW,YAAY,CAAC,GAAG,CAAC;IAE5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAc;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAsC;IAClE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA2B;IACvD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IACjD,wEAAwE;IACxE,OAAO,CAAC,GAAG,CAAwB;IAEnC;;;;;;;;OAQG;IACH,OAAO,CAAC,SAAS;gBAoBL,UAAU,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,cAAc;IASxD;;;;;;;;OAQG;IACH,OAAO,CAAC,gBAAgB;IAYxB;;;;OAIG;IACI,KAAK,CAAC,EAAE,EAAE,cAAc,GAAG,IAAI;IAItC;;;;;;;;OAQG;YACW,yBAAyB;IA6DvC;;OAEG;IACU,YAAY,CACvB,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC;QAAE,SAAS,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC;QAAC,QAAQ,EAAE,YAAY,CAAA;KAAE,CAAC;IAyVxE;;;;;;;;OAQG;IACU,SAAS,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAwErD;;;;;;;;;OASG;IACU,qBAAqB,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA2DnE;;;;;;;;OAQG;IACU,gBAAgB,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC;QAC9C,aAAa,EAAE,gCAAgC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;QAC5D,cAAc,EAAE,iCAAiC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;KAC/D,CAAC;IAoLF;;;;;;;;;;OAUG;IACU,YAAY,CACvB,EAAE,EAAE,GAAG,EACP,OAAO,EAAE,cAAc,CAAC,GAAG,CAAC,GAC3B,OAAO,CAAC,IAAI,CAAC;IAiLhB;;OAEG;IACU,YAAY,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAqCjD;;;;;;;;OAQG;IACU,WAAW,CAAC,KAAK,EAAE,iBAAiB,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAuFtE;;;;;;;OAOG;IACU,UAAU,CACrB,QAAQ,EAAE,oBAAoB,CAAC,GAAG,CAAC,GAClC,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;IAmFnC;;;;;;OAMG;YACW,iBAAiB;IAsF/B;;OAEG;IAEU,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtD;;OAEG;IACU,gBAAgB,CAC3B,QAAQ,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,GAC9B,OAAO,CAAC,IAAI,CAAC;CAIjB"}
|
|
@@ -524,6 +524,16 @@ class MemberStore {
|
|
|
524
524
|
console.info(`[MemberStore] getMemberPublicKeyHex: found publicKey in users collection for id=${idHex}`);
|
|
525
525
|
return userDoc.publicKey;
|
|
526
526
|
}
|
|
527
|
+
// Document exists but publicKey is empty/missing
|
|
528
|
+
if (userDoc) {
|
|
529
|
+
console.warn(`[MemberStore] getMemberPublicKeyHex: user document found for id=${idHex} but publicKey is empty`);
|
|
530
|
+
}
|
|
531
|
+
else {
|
|
532
|
+
console.warn(`[MemberStore] getMemberPublicKeyHex: no user document found in users collection for id=${idHex}`);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
else {
|
|
536
|
+
console.warn('[MemberStore] getMemberPublicKeyHex: no DB reference set, skipping fast path');
|
|
527
537
|
}
|
|
528
538
|
// Fallback — reconstruct from CBL blocks (works for createMember() members)
|
|
529
539
|
try {
|
|
@@ -860,7 +870,13 @@ class MemberStore {
|
|
|
860
870
|
// The garbage collector will handle unreferenced blocks
|
|
861
871
|
}
|
|
862
872
|
/**
|
|
863
|
-
* Update the member index
|
|
873
|
+
* Update the member index.
|
|
874
|
+
*
|
|
875
|
+
* Updates the in-memory indexes AND persists the entry to the
|
|
876
|
+
* `member_index` BrightDb collection (when `_db` is available) so that
|
|
877
|
+
* the data survives server restarts. Without this DB write, members
|
|
878
|
+
* created via `createMember()` / `register()` only existed in memory
|
|
879
|
+
* and were lost on restart.
|
|
864
880
|
*/
|
|
865
881
|
async updateIndex(entry) {
|
|
866
882
|
const provider = service_provider_1.ServiceProvider.getInstance().idProvider;
|
|
@@ -899,6 +915,46 @@ class MemberStore {
|
|
|
899
915
|
}
|
|
900
916
|
// Update member index
|
|
901
917
|
this.memberIndex.set(id, entry);
|
|
918
|
+
// ── Persist to the member_index BrightDb collection ──────────────
|
|
919
|
+
// This ensures the entry survives server restarts. The _queryIndexFromDb
|
|
920
|
+
// fallback queries this collection when the in-memory index is empty.
|
|
921
|
+
if (this._db) {
|
|
922
|
+
try {
|
|
923
|
+
const indexCol = this._db.collection('member_index');
|
|
924
|
+
const doc = {
|
|
925
|
+
id,
|
|
926
|
+
publicCBL: entry.publicCBL.toHex(),
|
|
927
|
+
privateCBL: entry.privateCBL.toHex(),
|
|
928
|
+
...(entry.publicProfileCBL
|
|
929
|
+
? { publicProfileCBL: entry.publicProfileCBL.toHex() }
|
|
930
|
+
: {}),
|
|
931
|
+
...(entry.privateProfileCBL
|
|
932
|
+
? { privateProfileCBL: entry.privateProfileCBL.toHex() }
|
|
933
|
+
: {}),
|
|
934
|
+
poolId: this._db.name ?? '',
|
|
935
|
+
type: entry.type,
|
|
936
|
+
status: entry.status,
|
|
937
|
+
lastUpdate: entry.lastUpdate.toISOString(),
|
|
938
|
+
...(entry.region ? { region: entry.region } : {}),
|
|
939
|
+
reputation: entry.reputation,
|
|
940
|
+
};
|
|
941
|
+
// Upsert: try update first, insert if not found
|
|
942
|
+
const existing = await indexCol.findOne({ id });
|
|
943
|
+
if (existing) {
|
|
944
|
+
await indexCol.updateOne({ id }, { $set: doc });
|
|
945
|
+
}
|
|
946
|
+
else {
|
|
947
|
+
await indexCol.insertOne(doc);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
catch (err) {
|
|
951
|
+
// Log but don't fail — the in-memory index is already updated.
|
|
952
|
+
// On restart, _queryIndexFromDb will miss this entry, but the
|
|
953
|
+
// users collection doc (written separately) may still allow
|
|
954
|
+
// partial recovery.
|
|
955
|
+
console.warn('[MemberStore] Failed to persist member_index entry to DB:', err instanceof Error ? err.message : String(err));
|
|
956
|
+
}
|
|
957
|
+
}
|
|
902
958
|
}
|
|
903
959
|
/**
|
|
904
960
|
* Query the member index.
|