@brightchain/brightchain-api-lib 0.15.0 → 0.17.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/package.json +4 -4
- package/src/browser.d.ts +13 -0
- package/src/browser.d.ts.map +1 -0
- package/src/browser.js +16 -0
- package/src/browser.js.map +1 -0
- package/src/index.d.ts +5 -1
- package/src/index.d.ts.map +1 -1
- package/src/index.js +7 -1
- package/src/index.js.map +1 -1
- package/src/lib/adapters/brightChainDbDocumentStoreAdapter.d.ts +24 -0
- package/src/lib/adapters/brightChainDbDocumentStoreAdapter.d.ts.map +1 -0
- package/src/lib/adapters/brightChainDbDocumentStoreAdapter.js +53 -0
- package/src/lib/adapters/brightChainDbDocumentStoreAdapter.js.map +1 -0
- package/src/lib/application-base.d.ts +8 -37
- package/src/lib/application-base.d.ts.map +1 -1
- package/src/lib/application-base.js +8 -80
- package/src/lib/application-base.js.map +1 -1
- package/src/lib/application.d.ts +56 -7
- package/src/lib/application.d.ts.map +1 -1
- package/src/lib/application.js +169 -134
- package/src/lib/application.js.map +1 -1
- package/src/lib/availability/gossipService.d.ts +20 -1
- package/src/lib/availability/gossipService.d.ts.map +1 -1
- package/src/lib/availability/gossipService.js +59 -0
- package/src/lib/availability/gossipService.js.map +1 -1
- package/src/lib/availability/index.d.ts +1 -0
- package/src/lib/availability/index.d.ts.map +1 -1
- package/src/lib/availability/index.js +1 -0
- package/src/lib/availability/index.js.map +1 -1
- package/src/lib/availability/poolDiscoveryService.d.ts +117 -0
- package/src/lib/availability/poolDiscoveryService.d.ts.map +1 -0
- package/src/lib/availability/poolDiscoveryService.js +218 -0
- package/src/lib/availability/poolDiscoveryService.js.map +1 -0
- package/src/lib/blockFetch/httpBlockFetchTransport.d.ts.map +1 -1
- package/src/lib/blockFetch/httpBlockFetchTransport.js.map +1 -1
- package/src/lib/constants.js +2 -2
- package/src/lib/constants.js.map +1 -1
- package/src/lib/controllers/api/blocks.d.ts.map +1 -1
- package/src/lib/controllers/api/blocks.js +290 -290
- package/src/lib/controllers/api/blocks.js.map +1 -1
- package/src/lib/controllers/api/brightpass.d.ts.map +1 -1
- package/src/lib/controllers/api/brightpass.js +270 -274
- package/src/lib/controllers/api/brightpass.js.map +1 -1
- package/src/lib/controllers/api/energy.d.ts.map +1 -1
- package/src/lib/controllers/api/energy.js +93 -93
- package/src/lib/controllers/api/energy.js.map +1 -1
- package/src/lib/controllers/api/health.d.ts +4 -4
- package/src/lib/controllers/api/health.d.ts.map +1 -1
- package/src/lib/controllers/api/health.js.map +1 -1
- package/src/lib/controllers/api/i18n.d.ts.map +1 -1
- package/src/lib/controllers/api/i18n.js +8 -8
- package/src/lib/controllers/api/i18n.js.map +1 -1
- package/src/lib/controllers/api/index.d.ts +1 -0
- package/src/lib/controllers/api/index.d.ts.map +1 -1
- package/src/lib/controllers/api/index.js +1 -0
- package/src/lib/controllers/api/index.js.map +1 -1
- package/src/lib/controllers/api/introspection.d.ts +60 -0
- package/src/lib/controllers/api/introspection.d.ts.map +1 -0
- package/src/lib/controllers/api/introspection.js +375 -0
- package/src/lib/controllers/api/introspection.js.map +1 -0
- package/src/lib/controllers/api/nodes.d.ts +7 -6
- package/src/lib/controllers/api/nodes.d.ts.map +1 -1
- package/src/lib/controllers/api/nodes.js.map +1 -1
- package/src/lib/controllers/api/quorum.d.ts.map +1 -1
- package/src/lib/controllers/api/quorum.js +483 -483
- package/src/lib/controllers/api/quorum.js.map +1 -1
- package/src/lib/controllers/api/sessions.d.ts.map +1 -1
- package/src/lib/controllers/api/sessions.js +8 -8
- package/src/lib/controllers/api/sessions.js.map +1 -1
- package/src/lib/controllers/api/sync.d.ts +6 -5
- package/src/lib/controllers/api/sync.d.ts.map +1 -1
- package/src/lib/controllers/api/sync.js.map +1 -1
- package/src/lib/controllers/api/user.d.ts.map +1 -1
- package/src/lib/controllers/api/user.js +260 -180
- package/src/lib/controllers/api/user.js.map +1 -1
- package/src/lib/controllers/base.d.ts +1 -2
- package/src/lib/controllers/base.d.ts.map +1 -1
- package/src/lib/controllers/base.js +0 -1
- package/src/lib/controllers/base.js.map +1 -1
- package/src/lib/databaseInit.d.ts +28 -0
- package/src/lib/databaseInit.d.ts.map +1 -0
- package/src/lib/databaseInit.js +107 -0
- package/src/lib/databaseInit.js.map +1 -0
- package/src/lib/enumerations/brightChainApiStrings.d.ts +4 -0
- package/src/lib/enumerations/brightChainApiStrings.d.ts.map +1 -1
- package/src/lib/enumerations/brightChainApiStrings.js +4 -0
- package/src/lib/enumerations/brightChainApiStrings.js.map +1 -1
- package/src/lib/enumerations/index.d.ts +1 -0
- package/src/lib/enumerations/index.d.ts.map +1 -1
- package/src/lib/enumerations/index.js +1 -0
- package/src/lib/enumerations/index.js.map +1 -1
- package/src/lib/enumerations/websocketMessageType.d.ts +5 -1
- package/src/lib/enumerations/websocketMessageType.d.ts.map +1 -1
- package/src/lib/enumerations/websocketMessageType.js +4 -0
- package/src/lib/enumerations/websocketMessageType.js.map +1 -1
- package/src/lib/environment.d.ts +5 -0
- package/src/lib/environment.d.ts.map +1 -1
- package/src/lib/environment.js +7 -0
- package/src/lib/environment.js.map +1 -1
- package/src/lib/errors/index.d.ts +1 -0
- package/src/lib/errors/index.d.ts.map +1 -1
- package/src/lib/errors/index.js +1 -0
- package/src/lib/errors/index.js.map +1 -1
- package/src/lib/errors/memberIndexSchemaValidationError.d.ts +6 -0
- package/src/lib/errors/memberIndexSchemaValidationError.d.ts.map +1 -0
- package/src/lib/errors/memberIndexSchemaValidationError.js +15 -0
- package/src/lib/errors/memberIndexSchemaValidationError.js.map +1 -0
- package/src/lib/factories/blockStoreFactory.d.ts +2 -13
- package/src/lib/factories/blockStoreFactory.d.ts.map +1 -1
- package/src/lib/factories/blockStoreFactory.js +5 -10
- package/src/lib/factories/blockStoreFactory.js.map +1 -1
- package/src/lib/interfaces/application.d.ts +7 -1
- package/src/lib/interfaces/application.d.ts.map +1 -1
- package/src/lib/interfaces/blocksHandlers.d.ts +3 -3
- package/src/lib/interfaces/blocksHandlers.d.ts.map +1 -1
- package/src/lib/interfaces/brightchain-init-result.d.ts +17 -0
- package/src/lib/interfaces/brightchain-init-result.d.ts.map +1 -0
- package/src/lib/interfaces/brightchain-init-result.js +9 -0
- package/src/lib/interfaces/brightchain-init-result.js.map +1 -0
- package/src/lib/interfaces/cblHandlers.d.ts +3 -2
- package/src/lib/interfaces/cblHandlers.d.ts.map +1 -1
- package/src/lib/interfaces/environment.d.ts +4 -0
- package/src/lib/interfaces/environment.d.ts.map +1 -1
- package/src/lib/interfaces/index.d.ts +5 -0
- package/src/lib/interfaces/index.d.ts.map +1 -1
- package/src/lib/interfaces/introspectionApiResponses.d.ts +66 -0
- package/src/lib/interfaces/introspectionApiResponses.d.ts.map +1 -0
- package/src/lib/interfaces/introspectionApiResponses.js +3 -0
- package/src/lib/interfaces/introspectionApiResponses.js.map +1 -0
- package/src/lib/interfaces/members-handlers.d.ts +11 -0
- package/src/lib/interfaces/members-handlers.d.ts.map +1 -0
- package/src/lib/interfaces/members-handlers.js +3 -0
- package/src/lib/interfaces/members-handlers.js.map +1 -0
- package/src/lib/interfaces/responses/api-backup-codes-response.d.ts +2 -5
- package/src/lib/interfaces/responses/api-backup-codes-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-challenge-response.d.ts +2 -5
- package/src/lib/interfaces/responses/api-challenge-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-code-count-response.d.ts +2 -5
- package/src/lib/interfaces/responses/api-code-count-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-detailed-health-response.d.ts +5 -0
- package/src/lib/interfaces/responses/api-detailed-health-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/api-detailed-health-response.js +3 -0
- package/src/lib/interfaces/responses/api-detailed-health-response.js.map +1 -0
- package/src/lib/interfaces/responses/api-discover-block-response.d.ts +5 -0
- package/src/lib/interfaces/responses/api-discover-block-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/api-discover-block-response.js +3 -0
- package/src/lib/interfaces/responses/api-discover-block-response.js.map +1 -0
- package/src/lib/interfaces/responses/api-error.d.ts +5 -0
- package/src/lib/interfaces/responses/api-error.d.ts.map +1 -0
- package/src/lib/interfaces/responses/api-error.js +3 -0
- package/src/lib/interfaces/responses/api-error.js.map +1 -0
- package/src/lib/interfaces/responses/api-express-validation-error.d.ts +7 -0
- package/src/lib/interfaces/responses/api-express-validation-error.d.ts.map +1 -0
- package/src/lib/interfaces/responses/api-express-validation-error.js +3 -0
- package/src/lib/interfaces/responses/api-express-validation-error.js.map +1 -0
- package/src/lib/interfaces/responses/api-get-block-response.d.ts +5 -0
- package/src/lib/interfaces/responses/api-get-block-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/api-get-block-response.js +3 -0
- package/src/lib/interfaces/responses/api-get-block-response.js.map +1 -0
- package/src/lib/interfaces/responses/api-get-node-response.d.ts +5 -0
- package/src/lib/interfaces/responses/api-get-node-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/api-get-node-response.js +3 -0
- package/src/lib/interfaces/responses/api-get-node-response.js.map +1 -0
- package/src/lib/interfaces/responses/api-health-response.d.ts +5 -0
- package/src/lib/interfaces/responses/api-health-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/api-health-response.js +3 -0
- package/src/lib/interfaces/responses/api-health-response.js.map +1 -0
- package/src/lib/interfaces/responses/api-list-nodes-response.d.ts +5 -0
- package/src/lib/interfaces/responses/api-list-nodes-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/api-list-nodes-response.js +3 -0
- package/src/lib/interfaces/responses/api-list-nodes-response.js.map +1 -0
- package/src/lib/interfaces/responses/api-login-response.d.ts +2 -14
- package/src/lib/interfaces/responses/api-login-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-members-response.d.ts +8 -0
- package/src/lib/interfaces/responses/api-members-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/api-members-response.js +3 -0
- package/src/lib/interfaces/responses/api-members-response.js.map +1 -0
- package/src/lib/interfaces/responses/api-mnemonic-response.d.ts +2 -5
- package/src/lib/interfaces/responses/api-mnemonic-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-reconcile-response.d.ts +5 -0
- package/src/lib/interfaces/responses/api-reconcile-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/api-reconcile-response.js +3 -0
- package/src/lib/interfaces/responses/api-reconcile-response.js.map +1 -0
- package/src/lib/interfaces/responses/api-register-node-response.d.ts +5 -0
- package/src/lib/interfaces/responses/api-register-node-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/api-register-node-response.js +3 -0
- package/src/lib/interfaces/responses/api-register-node-response.js.map +1 -0
- package/src/lib/interfaces/responses/api-registration-response.d.ts +2 -10
- package/src/lib/interfaces/responses/api-registration-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-replicate-block-response.d.ts +5 -0
- package/src/lib/interfaces/responses/api-replicate-block-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/api-replicate-block-response.js +3 -0
- package/src/lib/interfaces/responses/api-replicate-block-response.js.map +1 -0
- package/src/lib/interfaces/responses/api-request-user-response.d.ts +2 -6
- package/src/lib/interfaces/responses/api-request-user-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-status-code-response.d.ts +7 -0
- package/src/lib/interfaces/responses/api-status-code-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/api-status-code-response.js +3 -0
- package/src/lib/interfaces/responses/api-status-code-response.js.map +1 -0
- package/src/lib/interfaces/responses/api-store-block-response.d.ts +5 -0
- package/src/lib/interfaces/responses/api-store-block-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/api-store-block-response.js +3 -0
- package/src/lib/interfaces/responses/api-store-block-response.js.map +1 -0
- package/src/lib/interfaces/responses/api-store-cbl-response.d.ts +5 -0
- package/src/lib/interfaces/responses/api-store-cbl-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/api-store-cbl-response.js +3 -0
- package/src/lib/interfaces/responses/api-store-cbl-response.js.map +1 -0
- package/src/lib/interfaces/responses/api-sync-request-response.d.ts +5 -0
- package/src/lib/interfaces/responses/api-sync-request-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/api-sync-request-response.js +3 -0
- package/src/lib/interfaces/responses/api-sync-request-response.js.map +1 -0
- package/src/lib/interfaces/responses/block-data-response.d.ts +11 -0
- package/src/lib/interfaces/responses/block-data-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/block-data-response.js +3 -0
- package/src/lib/interfaces/responses/block-data-response.js.map +1 -0
- package/src/lib/interfaces/responses/block-location-response.d.ts +11 -0
- package/src/lib/interfaces/responses/block-location-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/block-location-response.js +3 -0
- package/src/lib/interfaces/responses/block-location-response.js.map +1 -0
- package/src/lib/interfaces/responses/index.d.ts +18 -0
- package/src/lib/interfaces/responses/index.d.ts.map +1 -1
- package/src/lib/interfaces/status-code-response.d.ts +1 -6
- package/src/lib/interfaces/status-code-response.d.ts.map +1 -1
- package/src/lib/interfaces/storage/client-session.d.ts +8 -0
- package/src/lib/interfaces/storage/client-session.d.ts.map +1 -0
- package/src/lib/interfaces/storage/client-session.js +3 -0
- package/src/lib/interfaces/storage/client-session.js.map +1 -0
- package/src/lib/interfaces/storage/collection.d.ts +9 -0
- package/src/lib/interfaces/storage/collection.d.ts.map +1 -0
- package/src/lib/interfaces/storage/collection.js +3 -0
- package/src/lib/interfaces/storage/collection.js.map +1 -0
- package/src/lib/interfaces/storage/database-lifecycle-hooks.d.ts +8 -0
- package/src/lib/interfaces/storage/database-lifecycle-hooks.d.ts.map +1 -0
- package/src/lib/interfaces/storage/database-lifecycle-hooks.js +3 -0
- package/src/lib/interfaces/storage/database-lifecycle-hooks.js.map +1 -0
- package/src/lib/interfaces/storage/database.d.ts +9 -0
- package/src/lib/interfaces/storage/database.d.ts.map +1 -0
- package/src/lib/interfaces/storage/database.js +3 -0
- package/src/lib/interfaces/storage/database.js.map +1 -0
- package/src/lib/interfaces/storage/document-types.d.ts +9 -0
- package/src/lib/interfaces/storage/document-types.d.ts.map +1 -0
- package/src/lib/interfaces/storage/document-types.js +10 -0
- package/src/lib/interfaces/storage/document-types.js.map +1 -0
- package/src/lib/interfaces/storage/index.d.ts +7 -0
- package/src/lib/interfaces/storage/index.d.ts.map +1 -0
- package/src/lib/interfaces/storage/index.js +7 -0
- package/src/lib/interfaces/storage/index.js.map +1 -0
- package/src/lib/interfaces/storage/memberIndexSchema.d.ts +11 -0
- package/src/lib/interfaces/storage/memberIndexSchema.d.ts.map +1 -0
- package/src/lib/interfaces/storage/memberIndexSchema.js +26 -0
- package/src/lib/interfaces/storage/memberIndexSchema.js.map +1 -0
- package/src/lib/interfaces/userApiResponse.d.ts +17 -0
- package/src/lib/interfaces/userApiResponse.d.ts.map +1 -0
- package/src/lib/interfaces/userApiResponse.js +3 -0
- package/src/lib/interfaces/userApiResponse.js.map +1 -0
- package/src/lib/interfaces/websocketMessages.d.ts +64 -1
- package/src/lib/interfaces/websocketMessages.d.ts.map +1 -1
- package/src/lib/middleware/index.d.ts +2 -0
- package/src/lib/middleware/index.d.ts.map +1 -0
- package/src/lib/middleware/index.js +6 -0
- package/src/lib/middleware/index.js.map +1 -0
- package/src/lib/middleware/validateBody.d.ts +13 -0
- package/src/lib/middleware/validateBody.d.ts.map +1 -0
- package/src/lib/middleware/validateBody.js +35 -0
- package/src/lib/middleware/validateBody.js.map +1 -0
- package/src/lib/middlewares/authentication.d.ts +2 -0
- package/src/lib/middlewares/authentication.d.ts.map +1 -1
- package/src/lib/middlewares/authentication.js.map +1 -1
- package/src/lib/routers/api.d.ts +27 -0
- package/src/lib/routers/api.d.ts.map +1 -1
- package/src/lib/routers/api.js +44 -0
- package/src/lib/routers/api.js.map +1 -1
- package/src/lib/routers/app.d.ts +22 -14
- package/src/lib/routers/app.d.ts.map +1 -1
- package/src/lib/routers/app.js +28 -116
- package/src/lib/routers/app.js.map +1 -1
- package/src/lib/services/auth.d.ts +3 -1
- package/src/lib/services/auth.d.ts.map +1 -1
- package/src/lib/services/auth.js +51 -4
- package/src/lib/services/auth.js.map +1 -1
- package/src/lib/services/brightchain-member-init.service.d.ts +66 -0
- package/src/lib/services/brightchain-member-init.service.d.ts.map +1 -0
- package/src/lib/services/brightchain-member-init.service.js +152 -0
- package/src/lib/services/brightchain-member-init.service.js.map +1 -0
- package/src/lib/services/brightpass.property.helpers.d.ts +23 -0
- package/src/lib/services/brightpass.property.helpers.d.ts.map +1 -0
- package/src/lib/services/brightpass.property.helpers.js +113 -0
- package/src/lib/services/brightpass.property.helpers.js.map +1 -0
- package/src/lib/services/clientWebSocketServer.d.ts +147 -0
- package/src/lib/services/clientWebSocketServer.d.ts.map +1 -0
- package/src/lib/services/clientWebSocketServer.js +437 -0
- package/src/lib/services/clientWebSocketServer.js.map +1 -0
- package/src/lib/services/index.d.ts +2 -0
- package/src/lib/services/index.d.ts.map +1 -1
- package/src/lib/services/index.js +2 -0
- package/src/lib/services/index.js.map +1 -1
- package/src/lib/stores/diskBlockAsyncStore.d.ts +4 -4
- package/src/lib/stores/diskBlockAsyncStore.d.ts.map +1 -1
- package/src/lib/stores/diskBlockAsyncStore.js.map +1 -1
- package/src/lib/stores/diskBlockStore.d.ts +82 -17
- package/src/lib/stores/diskBlockStore.d.ts.map +1 -1
- package/src/lib/stores/diskBlockStore.js +787 -19
- package/src/lib/stores/diskBlockStore.js.map +1 -1
- package/src/lib/stores/diskBlockSyncStore.d.ts +24 -5
- package/src/lib/stores/diskBlockSyncStore.d.ts.map +1 -1
- package/src/lib/stores/diskBlockSyncStore.js +30 -13
- package/src/lib/stores/diskBlockSyncStore.js.map +1 -1
- package/src/lib/upstream-stubs.d.ts +36 -0
- package/src/lib/upstream-stubs.d.ts.map +1 -0
- package/src/lib/upstream-stubs.js +43 -0
- package/src/lib/upstream-stubs.js.map +1 -0
- package/src/lib/validation/userValidation.d.ts +27 -0
- package/src/lib/validation/userValidation.d.ts.map +1 -0
- package/src/lib/validation/userValidation.js +70 -0
- package/src/lib/validation/userValidation.js.map +1 -0
|
@@ -1,16 +1,66 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.DiskBlockStore = void 0;
|
|
4
37
|
const brightchain_lib_1 = require("@brightchain/brightchain-lib");
|
|
5
38
|
const fs_1 = require("fs");
|
|
39
|
+
const promises_1 = require("fs/promises");
|
|
6
40
|
const path_1 = require("path");
|
|
7
41
|
/**
|
|
8
|
-
* DiskBlockStore provides
|
|
9
|
-
*
|
|
10
|
-
*
|
|
42
|
+
* DiskBlockStore provides filesystem-backed block storage implementing IBlockStore.
|
|
43
|
+
*
|
|
44
|
+
* Storage layout (simple flat structure):
|
|
45
|
+
* {basePath}/blocks/{checksumHex} - Raw block data files
|
|
46
|
+
* {basePath}/meta/{checksumHex}.json - Block metadata as JSON
|
|
47
|
+
* {basePath}/parity/{checksumHex}/ - Parity block data files
|
|
48
|
+
*
|
|
49
|
+
* This class also serves as a base class for DiskBlockAsyncStore and DiskBlockSyncStore,
|
|
50
|
+
* which use a more complex directory layout via the protected helper methods.
|
|
51
|
+
*
|
|
52
|
+
* @see IBlockStore for the interface definition
|
|
11
53
|
*/
|
|
12
54
|
class DiskBlockStore {
|
|
13
55
|
constructor(config) {
|
|
56
|
+
/**
|
|
57
|
+
* Optional FEC service for parity generation and recovery.
|
|
58
|
+
*/
|
|
59
|
+
this.fecService = null;
|
|
60
|
+
/**
|
|
61
|
+
* Track whether the blocks/meta directories have been created.
|
|
62
|
+
*/
|
|
63
|
+
this.dirsEnsured = false;
|
|
14
64
|
if (!config.storePath) {
|
|
15
65
|
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.StorePathRequired);
|
|
16
66
|
}
|
|
@@ -24,8 +74,62 @@ class DiskBlockStore {
|
|
|
24
74
|
(0, fs_1.mkdirSync)(config.storePath, { recursive: true });
|
|
25
75
|
}
|
|
26
76
|
}
|
|
77
|
+
// ─── Public Accessors ───────────────────────────────────────────────
|
|
78
|
+
get blockSize() {
|
|
79
|
+
return this._blockSize;
|
|
80
|
+
}
|
|
81
|
+
get storePath() {
|
|
82
|
+
return this._storePath;
|
|
83
|
+
}
|
|
84
|
+
setFecService(fecService) {
|
|
85
|
+
this.fecService = fecService;
|
|
86
|
+
}
|
|
87
|
+
getFecService() {
|
|
88
|
+
return this.fecService;
|
|
89
|
+
}
|
|
90
|
+
// ─── Simple Layout Path Helpers (for IBlockStore implementation) ─────
|
|
91
|
+
/** Directory for raw block data files: {basePath}/blocks/ */
|
|
92
|
+
get blocksDir() {
|
|
93
|
+
return (0, path_1.join)(this._storePath, 'blocks');
|
|
94
|
+
}
|
|
95
|
+
/** Directory for metadata JSON files: {basePath}/meta/ */
|
|
96
|
+
get metaDir() {
|
|
97
|
+
return (0, path_1.join)(this._storePath, 'meta');
|
|
98
|
+
}
|
|
99
|
+
/** Directory for parity data: {basePath}/parity/ */
|
|
100
|
+
get parityDir() {
|
|
101
|
+
return (0, path_1.join)(this._storePath, 'parity');
|
|
102
|
+
}
|
|
103
|
+
/** File path for a block's raw data */
|
|
104
|
+
blockFilePath(checksumHex) {
|
|
105
|
+
return (0, path_1.join)(this.blocksDir, checksumHex);
|
|
106
|
+
}
|
|
107
|
+
/** File path for a block's metadata JSON */
|
|
108
|
+
metaFilePath(checksumHex) {
|
|
109
|
+
return (0, path_1.join)(this.metaDir, `${checksumHex}.json`);
|
|
110
|
+
}
|
|
111
|
+
/** Directory path for a block's parity files */
|
|
112
|
+
parityBlockDir(checksumHex) {
|
|
113
|
+
return (0, path_1.join)(this.parityDir, checksumHex);
|
|
114
|
+
}
|
|
115
|
+
/** Ensure blocks/ and meta/ directories exist (lazy, once per instance) */
|
|
116
|
+
async ensureDirs() {
|
|
117
|
+
if (this.dirsEnsured)
|
|
118
|
+
return;
|
|
119
|
+
await (0, promises_1.mkdir)(this.blocksDir, { recursive: true });
|
|
120
|
+
await (0, promises_1.mkdir)(this.metaDir, { recursive: true });
|
|
121
|
+
this.dirsEnsured = true;
|
|
122
|
+
}
|
|
123
|
+
// ─── Key Conversion Helpers ─────────────────────────────────────────
|
|
124
|
+
keyToHex(key) {
|
|
125
|
+
return typeof key === 'string' ? key : key.toHex();
|
|
126
|
+
}
|
|
127
|
+
hexToChecksum(hex) {
|
|
128
|
+
return brightchain_lib_1.Checksum.fromHex(hex);
|
|
129
|
+
}
|
|
130
|
+
// ─── Protected Path Helpers (for subclass compatibility) ────────────
|
|
27
131
|
/**
|
|
28
|
-
* Get the directory path for a block
|
|
132
|
+
* Get the directory path for a block (complex layout used by subclasses).
|
|
29
133
|
* Directory structure: storePath/blockSize/checksumChar1/checksumChar2/
|
|
30
134
|
*/
|
|
31
135
|
blockDir(blockId, blockSize) {
|
|
@@ -37,7 +141,7 @@ class DiskBlockStore {
|
|
|
37
141
|
return (0, path_1.join)(this._storePath, blockSizeString, checksumString[0], checksumString[1]);
|
|
38
142
|
}
|
|
39
143
|
/**
|
|
40
|
-
* Get the file path for a block
|
|
144
|
+
* Get the file path for a block (complex layout used by subclasses).
|
|
41
145
|
* File structure: storePath/blockSize/checksumChar1/checksumChar2/fullChecksum
|
|
42
146
|
*/
|
|
43
147
|
blockPath(blockId, blockSize) {
|
|
@@ -49,20 +153,19 @@ class DiskBlockStore {
|
|
|
49
153
|
return (0, path_1.join)(this._storePath, blockSizeString, checksumString[0], checksumString[1], checksumString);
|
|
50
154
|
}
|
|
51
155
|
/**
|
|
52
|
-
* Get the metadata file path for a block
|
|
53
|
-
* Metadata files are stored alongside block files with a .m.json extension
|
|
156
|
+
* Get the metadata file path for a block (complex layout used by subclasses).
|
|
54
157
|
*/
|
|
55
158
|
metadataPath(blockId, blockSize) {
|
|
56
159
|
return this.blockPath(blockId, blockSize) + '.m.json';
|
|
57
160
|
}
|
|
58
161
|
/**
|
|
59
|
-
* Ensure the directory structure exists for a block
|
|
162
|
+
* Ensure the directory structure exists for a block (complex layout used by subclasses).
|
|
60
163
|
*/
|
|
61
164
|
ensureBlockPath(blockId, blockSize) {
|
|
62
|
-
const
|
|
63
|
-
if (!(0, fs_1.existsSync)(
|
|
165
|
+
const dir = this.blockDir(blockId, blockSize);
|
|
166
|
+
if (!(0, fs_1.existsSync)(dir)) {
|
|
64
167
|
try {
|
|
65
|
-
(0, fs_1.mkdirSync)(
|
|
168
|
+
(0, fs_1.mkdirSync)(dir, { recursive: true });
|
|
66
169
|
}
|
|
67
170
|
catch (error) {
|
|
68
171
|
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.BlockDirectoryCreationFailed, undefined, {
|
|
@@ -71,17 +174,682 @@ class DiskBlockStore {
|
|
|
71
174
|
}
|
|
72
175
|
}
|
|
73
176
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
177
|
+
// ─── IBlockStore: Core Block Operations ─────────────────────────────
|
|
178
|
+
async has(key) {
|
|
179
|
+
const keyHex = this.keyToHex(key);
|
|
180
|
+
try {
|
|
181
|
+
await (0, promises_1.access)(this.blockFilePath(keyHex));
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
async getData(key) {
|
|
189
|
+
const keyHex = this.keyToHex(key);
|
|
190
|
+
const filePath = this.blockFilePath(keyHex);
|
|
191
|
+
try {
|
|
192
|
+
await (0, promises_1.access)(filePath);
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.KeyNotFound, undefined, {
|
|
196
|
+
KEY: keyHex,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
const data = await (0, promises_1.readFile)(filePath);
|
|
200
|
+
const block = new brightchain_lib_1.RawDataBlock(this._blockSize, new Uint8Array(data));
|
|
201
|
+
// Record access in metadata
|
|
202
|
+
await this.touchMetadataAccess(keyHex);
|
|
203
|
+
return block;
|
|
204
|
+
}
|
|
205
|
+
async setData(block, options) {
|
|
206
|
+
const keyHex = block.idChecksum.toHex();
|
|
207
|
+
const filePath = this.blockFilePath(keyHex);
|
|
208
|
+
// Idempotent — block already exists
|
|
209
|
+
try {
|
|
210
|
+
await (0, promises_1.access)(filePath);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
// File doesn't exist, proceed to write
|
|
215
|
+
}
|
|
216
|
+
try {
|
|
217
|
+
block.validate();
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.BlockValidationFailed);
|
|
221
|
+
}
|
|
222
|
+
await this.ensureDirs();
|
|
223
|
+
// Write block data
|
|
224
|
+
await (0, promises_1.writeFile)(filePath, block.data);
|
|
225
|
+
// Write metadata
|
|
226
|
+
const metadata = (0, brightchain_lib_1.createDefaultBlockMetadata)(keyHex, block.data.length, keyHex, options);
|
|
227
|
+
await this.writeMetadata(keyHex, metadata);
|
|
228
|
+
// Generate parity blocks based on durability level
|
|
229
|
+
const durabilityLevel = options?.durabilityLevel ?? brightchain_lib_1.DurabilityLevel.Standard;
|
|
230
|
+
const parityCount = (0, brightchain_lib_1.getParityCountForDurability)(durabilityLevel);
|
|
231
|
+
if (parityCount > 0 && this.fecService) {
|
|
232
|
+
try {
|
|
233
|
+
await this.generateParityBlocks(keyHex, parityCount);
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
// Parity generation failure is non-fatal; block is still stored
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
async deleteData(key) {
|
|
241
|
+
const keyHex = this.keyToHex(key);
|
|
242
|
+
const filePath = this.blockFilePath(keyHex);
|
|
243
|
+
try {
|
|
244
|
+
await (0, promises_1.access)(filePath);
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.KeyNotFound);
|
|
248
|
+
}
|
|
249
|
+
// Delete block data
|
|
250
|
+
try {
|
|
251
|
+
await (0, promises_1.unlink)(filePath);
|
|
252
|
+
}
|
|
253
|
+
catch (error) {
|
|
254
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.BlockDeletionFailed, undefined, {
|
|
255
|
+
ERROR: error instanceof Error ? error.message : String(error),
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
// Delete metadata
|
|
259
|
+
try {
|
|
260
|
+
await (0, promises_1.unlink)(this.metaFilePath(keyHex));
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
// Metadata may not exist; non-fatal
|
|
264
|
+
}
|
|
265
|
+
// Delete parity directory
|
|
266
|
+
try {
|
|
267
|
+
const parDir = this.parityBlockDir(keyHex);
|
|
268
|
+
await (0, promises_1.access)(parDir);
|
|
269
|
+
const files = await (0, promises_1.readdir)(parDir);
|
|
270
|
+
for (const f of files) {
|
|
271
|
+
await (0, promises_1.unlink)((0, path_1.join)(parDir, f));
|
|
272
|
+
}
|
|
273
|
+
// Remove the directory itself via rmdir-like approach
|
|
274
|
+
const { rmdir } = await Promise.resolve().then(() => __importStar(require('fs/promises')));
|
|
275
|
+
await rmdir(parDir);
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
// Parity data may not exist; non-fatal
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
async getRandomBlocks(count) {
|
|
282
|
+
try {
|
|
283
|
+
await (0, promises_1.access)(this.blocksDir);
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
return [];
|
|
287
|
+
}
|
|
288
|
+
const files = await (0, promises_1.readdir)(this.blocksDir);
|
|
289
|
+
const actualCount = Math.min(count, files.length);
|
|
290
|
+
const shuffled = [...files].sort(() => Math.random() - 0.5);
|
|
291
|
+
const result = [];
|
|
292
|
+
for (let i = 0; i < actualCount; i++) {
|
|
293
|
+
try {
|
|
294
|
+
result.push(brightchain_lib_1.Checksum.fromHex(shuffled[i]));
|
|
295
|
+
}
|
|
296
|
+
catch {
|
|
297
|
+
// Skip files with non-checksum names
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return result;
|
|
301
|
+
}
|
|
302
|
+
get(key) {
|
|
303
|
+
const keyHex = this.keyToHex(key);
|
|
304
|
+
const filePath = this.blockFilePath(keyHex);
|
|
305
|
+
if (!(0, fs_1.existsSync)(filePath)) {
|
|
306
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.KeyNotFound, undefined, {
|
|
307
|
+
KEY: keyHex,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
const data = (0, fs_1.readFileSync)(filePath);
|
|
311
|
+
const checksum = typeof key === 'string' ? this.hexToChecksum(key) : key;
|
|
312
|
+
return (0, brightchain_lib_1.createBlockHandle)(
|
|
313
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
314
|
+
brightchain_lib_1.RawDataBlock, this._blockSize, new Uint8Array(data), checksum, true, true);
|
|
315
|
+
}
|
|
316
|
+
async put(key, data, options) {
|
|
317
|
+
const block = new brightchain_lib_1.RawDataBlock(this._blockSize, data);
|
|
318
|
+
await this.setData(block, options);
|
|
319
|
+
}
|
|
320
|
+
async delete(key) {
|
|
321
|
+
const checksum = typeof key === 'string' ? this.hexToChecksum(key) : key;
|
|
322
|
+
await this.deleteData(checksum);
|
|
323
|
+
}
|
|
324
|
+
// ─── IBlockStore: Metadata Operations ───────────────────────────────
|
|
325
|
+
async getMetadata(key) {
|
|
326
|
+
const keyHex = this.keyToHex(key);
|
|
327
|
+
return this.readMetadata(keyHex);
|
|
328
|
+
}
|
|
329
|
+
async updateMetadata(key, updates) {
|
|
330
|
+
const keyHex = this.keyToHex(key);
|
|
331
|
+
const existing = await this.readMetadata(keyHex);
|
|
332
|
+
if (!existing) {
|
|
333
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.KeyNotFound, undefined, {
|
|
334
|
+
KEY: keyHex,
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
const updated = {
|
|
338
|
+
...existing,
|
|
339
|
+
...updates,
|
|
340
|
+
blockId: existing.blockId, // Prevent blockId from being changed
|
|
341
|
+
};
|
|
342
|
+
await this.writeMetadata(keyHex, updated);
|
|
343
|
+
}
|
|
344
|
+
// ─── IBlockStore: FEC/Durability Operations ─────────────────────────
|
|
345
|
+
async generateParityBlocks(key, parityCount) {
|
|
346
|
+
const keyHex = this.keyToHex(key);
|
|
347
|
+
if (!this.fecService) {
|
|
348
|
+
throw new brightchain_lib_1.FecError(brightchain_lib_1.FecErrorType.FecEncodingFailed, undefined, {
|
|
349
|
+
ERROR: 'FEC service is not available',
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
if (!(await this.has(key))) {
|
|
353
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.KeyNotFound, undefined, {
|
|
354
|
+
KEY: keyHex,
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
const isAvailable = await this.fecService.isAvailable();
|
|
358
|
+
if (!isAvailable) {
|
|
359
|
+
throw new brightchain_lib_1.FecError(brightchain_lib_1.FecErrorType.FecEncodingFailed, undefined, {
|
|
360
|
+
ERROR: 'FEC service is not available in this environment',
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
const blockData = await (0, promises_1.readFile)(this.blockFilePath(keyHex));
|
|
364
|
+
const parityData = await this.fecService.createParityData(new Uint8Array(blockData), parityCount);
|
|
365
|
+
// Store parity data to disk
|
|
366
|
+
const parDir = this.parityBlockDir(keyHex);
|
|
367
|
+
await (0, promises_1.mkdir)(parDir, { recursive: true });
|
|
368
|
+
const checksumService = (0, brightchain_lib_1.getGlobalServiceProvider)().checksumService;
|
|
369
|
+
const parityBlockIds = [];
|
|
370
|
+
for (let i = 0; i < parityData.length; i++) {
|
|
371
|
+
const parityId = checksumService
|
|
372
|
+
.calculateChecksum(parityData[i].data)
|
|
373
|
+
.toHex();
|
|
374
|
+
parityBlockIds.push(parityId);
|
|
375
|
+
await (0, promises_1.writeFile)((0, path_1.join)(parDir, `${i}.parity`), JSON.stringify({
|
|
376
|
+
id: parityId,
|
|
377
|
+
index: parityData[i].index,
|
|
378
|
+
data: Array.from(parityData[i].data),
|
|
379
|
+
}));
|
|
380
|
+
}
|
|
381
|
+
// Update metadata with parity block IDs
|
|
382
|
+
const meta = await this.readMetadata(keyHex);
|
|
383
|
+
if (meta) {
|
|
384
|
+
await this.writeMetadata(keyHex, { ...meta, parityBlockIds });
|
|
385
|
+
}
|
|
386
|
+
return parityBlockIds.map((id) => brightchain_lib_1.Checksum.fromHex(id));
|
|
387
|
+
}
|
|
388
|
+
async getParityBlocks(key) {
|
|
389
|
+
const keyHex = this.keyToHex(key);
|
|
390
|
+
const meta = await this.readMetadata(keyHex);
|
|
391
|
+
if (!meta)
|
|
392
|
+
return [];
|
|
393
|
+
return meta.parityBlockIds.map((id) => brightchain_lib_1.Checksum.fromHex(id));
|
|
394
|
+
}
|
|
395
|
+
async recoverBlock(key) {
|
|
396
|
+
const keyHex = this.keyToHex(key);
|
|
397
|
+
if (!this.fecService) {
|
|
398
|
+
return { success: false, error: 'FEC service is not available' };
|
|
399
|
+
}
|
|
400
|
+
const isAvailable = await this.fecService.isAvailable();
|
|
401
|
+
if (!isAvailable) {
|
|
402
|
+
return {
|
|
403
|
+
success: false,
|
|
404
|
+
error: 'FEC service is not available in this environment',
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
// Load parity data from disk
|
|
408
|
+
const parityData = await this.loadParityFromDisk(keyHex);
|
|
409
|
+
if (parityData.length === 0) {
|
|
410
|
+
return { success: false, error: 'No parity data available' };
|
|
411
|
+
}
|
|
412
|
+
const meta = await this.readMetadata(keyHex);
|
|
413
|
+
if (!meta) {
|
|
414
|
+
return { success: false, error: 'Block metadata not found' };
|
|
415
|
+
}
|
|
416
|
+
try {
|
|
417
|
+
let corruptedData = null;
|
|
418
|
+
try {
|
|
419
|
+
const raw = await (0, promises_1.readFile)(this.blockFilePath(keyHex));
|
|
420
|
+
corruptedData = new Uint8Array(raw);
|
|
421
|
+
}
|
|
422
|
+
catch {
|
|
423
|
+
// Block may be missing entirely
|
|
424
|
+
}
|
|
425
|
+
const result = await this.fecService.recoverFileData(corruptedData, parityData, meta.size);
|
|
426
|
+
if (result.recovered) {
|
|
427
|
+
const recoveredBlock = new brightchain_lib_1.RawDataBlock(this._blockSize, new Uint8Array(result.data));
|
|
428
|
+
await this.ensureDirs();
|
|
429
|
+
await (0, promises_1.writeFile)(this.blockFilePath(keyHex), recoveredBlock.data);
|
|
430
|
+
return { success: true, recoveredBlock };
|
|
431
|
+
}
|
|
432
|
+
return {
|
|
433
|
+
success: false,
|
|
434
|
+
error: 'Recovery failed: insufficient parity data',
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
catch (error) {
|
|
438
|
+
return {
|
|
439
|
+
success: false,
|
|
440
|
+
error: error instanceof Error ? error.message : 'Unknown recovery error',
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
async verifyBlockIntegrity(key) {
|
|
445
|
+
const keyHex = this.keyToHex(key);
|
|
446
|
+
if (!this.fecService) {
|
|
447
|
+
return this.has(key);
|
|
448
|
+
}
|
|
449
|
+
const isAvailable = await this.fecService.isAvailable();
|
|
450
|
+
if (!isAvailable) {
|
|
451
|
+
return this.has(key);
|
|
452
|
+
}
|
|
453
|
+
try {
|
|
454
|
+
await (0, promises_1.access)(this.blockFilePath(keyHex));
|
|
455
|
+
}
|
|
456
|
+
catch {
|
|
457
|
+
return false;
|
|
458
|
+
}
|
|
459
|
+
const parityData = await this.loadParityFromDisk(keyHex);
|
|
460
|
+
if (parityData.length === 0) {
|
|
461
|
+
return true; // No parity data — can only verify block exists
|
|
462
|
+
}
|
|
463
|
+
try {
|
|
464
|
+
const blockData = await (0, promises_1.readFile)(this.blockFilePath(keyHex));
|
|
465
|
+
return await this.fecService.verifyFileIntegrity(new Uint8Array(blockData), parityData);
|
|
466
|
+
}
|
|
467
|
+
catch {
|
|
468
|
+
return false;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
// ─── IBlockStore: Replication Operations ─────────────────────────────
|
|
472
|
+
async getBlocksPendingReplication() {
|
|
473
|
+
return this.findBlocksByReplicationStatus(brightchain_lib_1.ReplicationStatus.Pending, true);
|
|
474
|
+
}
|
|
475
|
+
async getUnderReplicatedBlocks() {
|
|
476
|
+
return this.findBlocksByReplicationStatus(brightchain_lib_1.ReplicationStatus.UnderReplicated, false);
|
|
477
|
+
}
|
|
478
|
+
async recordReplication(key, nodeId) {
|
|
479
|
+
const keyHex = this.keyToHex(key);
|
|
480
|
+
const meta = await this.readMetadata(keyHex);
|
|
481
|
+
if (!meta) {
|
|
482
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.KeyNotFound, undefined, {
|
|
483
|
+
KEY: keyHex,
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
const replicaNodeIds = [...meta.replicaNodeIds];
|
|
487
|
+
if (!replicaNodeIds.includes(nodeId)) {
|
|
488
|
+
replicaNodeIds.push(nodeId);
|
|
489
|
+
}
|
|
490
|
+
let replicationStatus = meta.replicationStatus;
|
|
491
|
+
if (replicaNodeIds.length >= meta.targetReplicationFactor) {
|
|
492
|
+
replicationStatus = brightchain_lib_1.ReplicationStatus.Replicated;
|
|
493
|
+
}
|
|
494
|
+
else if (replicaNodeIds.length > 0) {
|
|
495
|
+
replicationStatus = brightchain_lib_1.ReplicationStatus.UnderReplicated;
|
|
496
|
+
}
|
|
497
|
+
await this.writeMetadata(keyHex, {
|
|
498
|
+
...meta,
|
|
499
|
+
replicaNodeIds,
|
|
500
|
+
replicationStatus,
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
async recordReplicaLoss(key, nodeId) {
|
|
504
|
+
const keyHex = this.keyToHex(key);
|
|
505
|
+
const meta = await this.readMetadata(keyHex);
|
|
506
|
+
if (!meta) {
|
|
507
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.KeyNotFound, undefined, {
|
|
508
|
+
KEY: keyHex,
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
const replicaNodeIds = meta.replicaNodeIds.filter((id) => id !== nodeId);
|
|
512
|
+
let replicationStatus = meta.replicationStatus;
|
|
513
|
+
if (meta.targetReplicationFactor > 0) {
|
|
514
|
+
if (replicaNodeIds.length >= meta.targetReplicationFactor) {
|
|
515
|
+
replicationStatus = brightchain_lib_1.ReplicationStatus.Replicated;
|
|
516
|
+
}
|
|
517
|
+
else if (replicaNodeIds.length > 0) {
|
|
518
|
+
replicationStatus = brightchain_lib_1.ReplicationStatus.UnderReplicated;
|
|
519
|
+
}
|
|
520
|
+
else {
|
|
521
|
+
replicationStatus = brightchain_lib_1.ReplicationStatus.Pending;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
await this.writeMetadata(keyHex, {
|
|
525
|
+
...meta,
|
|
526
|
+
replicaNodeIds,
|
|
527
|
+
replicationStatus,
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
// ─── IBlockStore: XOR Brightening Operations ────────────────────────
|
|
531
|
+
async brightenBlock(key, randomBlockCount) {
|
|
532
|
+
const keyHex = this.keyToHex(key);
|
|
533
|
+
if (!(await this.has(key))) {
|
|
534
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.KeyNotFound, undefined, {
|
|
535
|
+
KEY: keyHex,
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
const randomBlockChecksums = await this.getRandomBlocks(randomBlockCount);
|
|
539
|
+
if (randomBlockChecksums.length < randomBlockCount) {
|
|
540
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.InsufficientRandomBlocks, undefined, {
|
|
541
|
+
REQUESTED: randomBlockCount.toString(),
|
|
542
|
+
AVAILABLE: randomBlockChecksums.length.toString(),
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
const sourceData = await (0, promises_1.readFile)(this.blockFilePath(keyHex));
|
|
546
|
+
const allBlockData = [new Uint8Array(sourceData)];
|
|
547
|
+
for (const checksum of randomBlockChecksums) {
|
|
548
|
+
const block = await this.getData(checksum);
|
|
549
|
+
allBlockData.push(block.data);
|
|
550
|
+
}
|
|
551
|
+
const brightenedData = brightchain_lib_1.XorService.xorMultiple(allBlockData);
|
|
552
|
+
const brightenedBlock = new brightchain_lib_1.RawDataBlock(this._blockSize, brightenedData);
|
|
553
|
+
const brightenedBlockId = brightenedBlock.idChecksum.toHex();
|
|
554
|
+
if (!(await this.has(brightenedBlockId))) {
|
|
555
|
+
await this.setData(brightenedBlock);
|
|
556
|
+
}
|
|
557
|
+
return {
|
|
558
|
+
brightenedBlockId,
|
|
559
|
+
randomBlockIds: randomBlockChecksums.map((c) => c.toHex()),
|
|
560
|
+
originalBlockId: keyHex,
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
// ─── IBlockStore: CBL Whitening Operations ──────────────────────────
|
|
564
|
+
async storeCBLWithWhitening(cblData, options) {
|
|
565
|
+
if (!cblData || cblData.length === 0) {
|
|
566
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.BlockValidationFailed, undefined, {
|
|
567
|
+
ERROR: 'CBL data cannot be empty',
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
const paddedCbl = (0, brightchain_lib_1.padToBlockSize)(cblData, this._blockSize);
|
|
571
|
+
if (paddedCbl.length > this._blockSize) {
|
|
572
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.BlockValidationFailed, undefined, {
|
|
573
|
+
ERROR: `CBL data too large: padded size (${paddedCbl.length}) exceeds block size (${this._blockSize})`,
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
const randomBlock = await this.selectOrGenerateRandomizer(paddedCbl.length);
|
|
577
|
+
const xorResult = (0, brightchain_lib_1.xorArrays)(paddedCbl, randomBlock);
|
|
578
|
+
let block1Stored = false;
|
|
579
|
+
let block1Id = '';
|
|
580
|
+
try {
|
|
581
|
+
const block1 = new brightchain_lib_1.RawDataBlock(this._blockSize, randomBlock);
|
|
582
|
+
const block1Checksum = block1.idChecksum;
|
|
583
|
+
if (!(await this.has(block1Checksum))) {
|
|
584
|
+
await this.setData(block1, options);
|
|
585
|
+
block1Stored = true;
|
|
586
|
+
}
|
|
587
|
+
block1Id = block1Checksum.toHex();
|
|
588
|
+
const block2 = new brightchain_lib_1.RawDataBlock(this._blockSize, xorResult);
|
|
589
|
+
await this.setData(block2, options);
|
|
590
|
+
const block2Id = block2.idChecksum.toHex();
|
|
591
|
+
let block1ParityIds;
|
|
592
|
+
let block2ParityIds;
|
|
593
|
+
const block1Meta = await this.getMetadata(block1Id);
|
|
594
|
+
if (block1Meta?.parityBlockIds?.length) {
|
|
595
|
+
block1ParityIds = block1Meta.parityBlockIds;
|
|
596
|
+
}
|
|
597
|
+
const block2Meta = await this.getMetadata(block2Id);
|
|
598
|
+
if (block2Meta?.parityBlockIds?.length) {
|
|
599
|
+
block2ParityIds = block2Meta.parityBlockIds;
|
|
600
|
+
}
|
|
601
|
+
const magnetUrl = this.generateCBLMagnetUrl(block1Id, block2Id, this._blockSize, block1ParityIds, block2ParityIds, options?.isEncrypted);
|
|
602
|
+
return {
|
|
603
|
+
blockId1: block1Id,
|
|
604
|
+
blockId2: block2Id,
|
|
605
|
+
blockSize: this._blockSize,
|
|
606
|
+
magnetUrl,
|
|
607
|
+
block1ParityIds,
|
|
608
|
+
block2ParityIds,
|
|
609
|
+
isEncrypted: options?.isEncrypted,
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
catch (error) {
|
|
613
|
+
if (block1Stored && block1Id) {
|
|
614
|
+
try {
|
|
615
|
+
await this.deleteData(this.hexToChecksum(block1Id));
|
|
616
|
+
}
|
|
617
|
+
catch {
|
|
618
|
+
// Ignore rollback errors
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
throw error;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
async retrieveCBL(blockId1, blockId2, block1ParityIds, block2ParityIds) {
|
|
625
|
+
const b1Checksum = typeof blockId1 === 'string' ? this.hexToChecksum(blockId1) : blockId1;
|
|
626
|
+
let block1Data;
|
|
627
|
+
try {
|
|
628
|
+
block1Data = await this.getData(b1Checksum);
|
|
629
|
+
}
|
|
630
|
+
catch (error) {
|
|
631
|
+
if (block1ParityIds?.length) {
|
|
632
|
+
const recovery = await this.recoverBlock(b1Checksum);
|
|
633
|
+
if (recovery.success && recovery.recoveredBlock) {
|
|
634
|
+
block1Data = recovery.recoveredBlock;
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.KeyNotFound, undefined, {
|
|
638
|
+
KEY: this.keyToHex(blockId1),
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
else {
|
|
643
|
+
throw error;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
const b2Checksum = typeof blockId2 === 'string' ? this.hexToChecksum(blockId2) : blockId2;
|
|
647
|
+
let block2Data;
|
|
648
|
+
try {
|
|
649
|
+
block2Data = await this.getData(b2Checksum);
|
|
650
|
+
}
|
|
651
|
+
catch (error) {
|
|
652
|
+
if (block2ParityIds?.length) {
|
|
653
|
+
const recovery = await this.recoverBlock(b2Checksum);
|
|
654
|
+
if (recovery.success && recovery.recoveredBlock) {
|
|
655
|
+
block2Data = recovery.recoveredBlock;
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.KeyNotFound, undefined, {
|
|
659
|
+
KEY: this.keyToHex(blockId2),
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
else {
|
|
664
|
+
throw error;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
const reconstructedPadded = (0, brightchain_lib_1.xorArrays)(block1Data.data, block2Data.data);
|
|
668
|
+
return (0, brightchain_lib_1.unpadCblData)(reconstructedPadded);
|
|
669
|
+
}
|
|
670
|
+
parseCBLMagnetUrl(magnetUrl) {
|
|
671
|
+
if (!magnetUrl || !magnetUrl.startsWith('magnet:?')) {
|
|
672
|
+
throw new Error('Invalid magnet URL format');
|
|
673
|
+
}
|
|
674
|
+
const queryString = magnetUrl.substring('magnet:?'.length);
|
|
675
|
+
const params = new URLSearchParams(queryString);
|
|
676
|
+
const xt = params.get('xt');
|
|
677
|
+
if (xt !== 'urn:brightchain:cbl') {
|
|
678
|
+
throw new Error('Invalid magnet URL: wrong xt parameter');
|
|
679
|
+
}
|
|
680
|
+
const blockId1 = params.get('b1');
|
|
681
|
+
const blockId2 = params.get('b2');
|
|
682
|
+
const blockSizeStr = params.get('bs');
|
|
683
|
+
if (!blockId1)
|
|
684
|
+
throw new Error('Invalid magnet URL: missing b1');
|
|
685
|
+
if (!blockId2)
|
|
686
|
+
throw new Error('Invalid magnet URL: missing b2');
|
|
687
|
+
if (!blockSizeStr)
|
|
688
|
+
throw new Error('Invalid magnet URL: missing bs');
|
|
689
|
+
const blockSize = parseInt(blockSizeStr, 10);
|
|
690
|
+
if (isNaN(blockSize) || blockSize <= 0) {
|
|
691
|
+
throw new Error('Invalid magnet URL: invalid block size');
|
|
692
|
+
}
|
|
693
|
+
const p1Param = params.get('p1');
|
|
694
|
+
const p2Param = params.get('p2');
|
|
695
|
+
const block1ParityIds = p1Param
|
|
696
|
+
? p1Param.split(',').filter((id) => id)
|
|
697
|
+
: undefined;
|
|
698
|
+
const block2ParityIds = p2Param
|
|
699
|
+
? p2Param.split(',').filter((id) => id)
|
|
700
|
+
: undefined;
|
|
701
|
+
const isEncrypted = params.get('enc') === '1';
|
|
702
|
+
return {
|
|
703
|
+
blockId1,
|
|
704
|
+
blockId2,
|
|
705
|
+
blockSize,
|
|
706
|
+
block1ParityIds,
|
|
707
|
+
block2ParityIds,
|
|
708
|
+
isEncrypted,
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
generateCBLMagnetUrl(blockId1, blockId2, blockSize, block1ParityIds, block2ParityIds, isEncrypted) {
|
|
712
|
+
const b1Id = typeof blockId1 === 'string' ? blockId1 : blockId1.toHex();
|
|
713
|
+
const b2Id = typeof blockId2 === 'string' ? blockId2 : blockId2.toHex();
|
|
714
|
+
const params = new URLSearchParams();
|
|
715
|
+
params.set('xt', 'urn:brightchain:cbl');
|
|
716
|
+
params.set('bs', blockSize.toString());
|
|
717
|
+
params.set('b1', b1Id);
|
|
718
|
+
params.set('b2', b2Id);
|
|
719
|
+
if (block1ParityIds?.length) {
|
|
720
|
+
params.set('p1', block1ParityIds.join(','));
|
|
721
|
+
}
|
|
722
|
+
if (block2ParityIds?.length) {
|
|
723
|
+
params.set('p2', block2ParityIds.join(','));
|
|
724
|
+
}
|
|
725
|
+
if (isEncrypted) {
|
|
726
|
+
params.set('enc', '1');
|
|
727
|
+
}
|
|
728
|
+
return `magnet:?${params.toString()}`;
|
|
729
|
+
}
|
|
730
|
+
// ─── Private Helpers ────────────────────────────────────────────────
|
|
731
|
+
/** Read metadata JSON from disk, returning null if not found. */
|
|
732
|
+
async readMetadata(keyHex) {
|
|
733
|
+
const filePath = this.metaFilePath(keyHex);
|
|
734
|
+
try {
|
|
735
|
+
await (0, promises_1.access)(filePath);
|
|
736
|
+
}
|
|
737
|
+
catch {
|
|
738
|
+
return null;
|
|
739
|
+
}
|
|
740
|
+
try {
|
|
741
|
+
const raw = await (0, promises_1.readFile)(filePath, 'utf-8');
|
|
742
|
+
const parsed = JSON.parse(raw);
|
|
743
|
+
return {
|
|
744
|
+
...parsed,
|
|
745
|
+
createdAt: new Date(parsed.createdAt),
|
|
746
|
+
expiresAt: parsed.expiresAt ? new Date(parsed.expiresAt) : null,
|
|
747
|
+
lastAccessedAt: new Date(parsed.lastAccessedAt),
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
catch {
|
|
751
|
+
return null;
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
/** Write metadata JSON to disk. */
|
|
755
|
+
async writeMetadata(keyHex, metadata) {
|
|
756
|
+
await this.ensureDirs();
|
|
757
|
+
const filePath = this.metaFilePath(keyHex);
|
|
758
|
+
await (0, promises_1.writeFile)(filePath, JSON.stringify(metadata, null, 2), 'utf-8');
|
|
759
|
+
}
|
|
760
|
+
/** Update access count and timestamp in metadata. */
|
|
761
|
+
async touchMetadataAccess(keyHex) {
|
|
762
|
+
const meta = await this.readMetadata(keyHex);
|
|
763
|
+
if (meta) {
|
|
764
|
+
meta.accessCount += 1;
|
|
765
|
+
meta.lastAccessedAt = new Date();
|
|
766
|
+
await this.writeMetadata(keyHex, meta);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
/** Load parity data from disk for a given block. */
|
|
770
|
+
async loadParityFromDisk(keyHex) {
|
|
771
|
+
const parDir = this.parityBlockDir(keyHex);
|
|
772
|
+
try {
|
|
773
|
+
await (0, promises_1.access)(parDir);
|
|
774
|
+
}
|
|
775
|
+
catch {
|
|
776
|
+
return [];
|
|
777
|
+
}
|
|
778
|
+
const files = await (0, promises_1.readdir)(parDir);
|
|
779
|
+
const parityFiles = files.filter((f) => f.endsWith('.parity')).sort();
|
|
780
|
+
const result = [];
|
|
781
|
+
for (const f of parityFiles) {
|
|
782
|
+
try {
|
|
783
|
+
const raw = await (0, promises_1.readFile)((0, path_1.join)(parDir, f), 'utf-8');
|
|
784
|
+
const parsed = JSON.parse(raw);
|
|
785
|
+
result.push({
|
|
786
|
+
index: parsed.index,
|
|
787
|
+
data: new Uint8Array(parsed.data),
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
catch {
|
|
791
|
+
// Skip corrupt parity files
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
return result;
|
|
795
|
+
}
|
|
796
|
+
/** Scan all metadata files and find blocks matching a replication status. */
|
|
797
|
+
async findBlocksByReplicationStatus(status, requirePositiveTarget) {
|
|
798
|
+
try {
|
|
799
|
+
await (0, promises_1.access)(this.metaDir);
|
|
800
|
+
}
|
|
801
|
+
catch {
|
|
802
|
+
return [];
|
|
803
|
+
}
|
|
804
|
+
const files = await (0, promises_1.readdir)(this.metaDir);
|
|
805
|
+
const result = [];
|
|
806
|
+
for (const f of files) {
|
|
807
|
+
if (!f.endsWith('.json'))
|
|
808
|
+
continue;
|
|
809
|
+
const keyHex = f.replace('.json', '');
|
|
810
|
+
const meta = await this.readMetadata(keyHex);
|
|
811
|
+
if (!meta)
|
|
812
|
+
continue;
|
|
813
|
+
if (meta.replicationStatus === status) {
|
|
814
|
+
if (requirePositiveTarget && meta.targetReplicationFactor <= 0) {
|
|
815
|
+
continue;
|
|
816
|
+
}
|
|
817
|
+
try {
|
|
818
|
+
result.push(brightchain_lib_1.Checksum.fromHex(keyHex));
|
|
819
|
+
}
|
|
820
|
+
catch {
|
|
821
|
+
// Skip invalid checksums
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
return result;
|
|
79
826
|
}
|
|
80
827
|
/**
|
|
81
|
-
*
|
|
828
|
+
* Select an existing block as a randomizer, or generate a new one.
|
|
829
|
+
* Following OFFSystem principles: preferentially reuse existing blocks.
|
|
82
830
|
*/
|
|
83
|
-
|
|
84
|
-
|
|
831
|
+
async selectOrGenerateRandomizer(size) {
|
|
832
|
+
try {
|
|
833
|
+
await (0, promises_1.access)(this.blocksDir);
|
|
834
|
+
const files = await (0, promises_1.readdir)(this.blocksDir);
|
|
835
|
+
if (files.length > 0) {
|
|
836
|
+
const randomIndex = Math.floor(Math.random() * files.length);
|
|
837
|
+
const selectedFile = files[randomIndex];
|
|
838
|
+
try {
|
|
839
|
+
const data = await (0, promises_1.readFile)((0, path_1.join)(this.blocksDir, selectedFile));
|
|
840
|
+
if (data.length >= size) {
|
|
841
|
+
return new Uint8Array(data.subarray(0, size));
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
catch {
|
|
845
|
+
// Fall through to generation
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
catch {
|
|
850
|
+
// blocksDir doesn't exist yet; fall through
|
|
851
|
+
}
|
|
852
|
+
return brightchain_lib_1.XorService.generateKey(size);
|
|
85
853
|
}
|
|
86
854
|
}
|
|
87
855
|
exports.DiskBlockStore = DiskBlockStore;
|