@brightchain/brightchain-api-lib 0.23.25 → 0.24.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 +5 -5
- package/src/lib/__tests__/fixtures/mock-backend-brightchain-member.d.ts.map +1 -1
- package/src/lib/__tests__/fixtures/mock-backend-brightchain-member.js +11 -0
- package/src/lib/__tests__/fixtures/mock-backend-brightchain-member.js.map +1 -1
- package/src/lib/__tests__/fixtures/mocked-model.js +63 -60
- package/src/lib/__tests__/fixtures/mocked-model.js.map +1 -1
- package/src/lib/application.d.ts +1 -1
- package/src/lib/application.d.ts.map +1 -1
- package/src/lib/application.js +103 -34
- package/src/lib/application.js.map +1 -1
- package/src/lib/auth/aclEnforcedAvailability.js +4 -0
- package/src/lib/auth/aclEnforcedAvailability.js.map +1 -1
- package/src/lib/auth/aclEnforcedBlockStore.js +7 -0
- package/src/lib/auth/aclEnforcedBlockStore.js.map +1 -1
- package/src/lib/auth/ecdsaNodeAuthenticator.js +1 -0
- package/src/lib/auth/ecdsaNodeAuthenticator.js.map +1 -1
- package/src/lib/auth/poolAclBootstrap.js +2 -0
- package/src/lib/auth/poolAclBootstrap.js.map +1 -1
- package/src/lib/auth/poolAclStore.js +2 -1
- package/src/lib/auth/poolAclStore.js.map +1 -1
- package/src/lib/auth/poolAclUpdater.js +4 -0
- package/src/lib/auth/poolAclUpdater.js.map +1 -1
- package/src/lib/availability/availabilityMetrics.js +43 -45
- package/src/lib/availability/availabilityMetrics.js.map +1 -1
- package/src/lib/availability/availabilityService.js +26 -20
- package/src/lib/availability/availabilityService.js.map +1 -1
- package/src/lib/availability/blockRegistry.js +46 -25
- package/src/lib/availability/blockRegistry.js.map +1 -1
- package/src/lib/availability/discoveryProtocol.js +10 -8
- package/src/lib/availability/discoveryProtocol.js.map +1 -1
- package/src/lib/availability/gossipService.js +56 -45
- package/src/lib/availability/gossipService.js.map +1 -1
- package/src/lib/availability/heartbeatMonitor.js +22 -20
- package/src/lib/availability/heartbeatMonitor.js.map +1 -1
- package/src/lib/availability/poolDiscoveryService.js +7 -1
- package/src/lib/availability/poolDiscoveryService.js.map +1 -1
- package/src/lib/availability/quorumGossipHandler.js +13 -6
- package/src/lib/availability/quorumGossipHandler.js.map +1 -1
- package/src/lib/availability/reconciliationService.js +18 -12
- package/src/lib/availability/reconciliationService.js.map +1 -1
- package/src/lib/blockFetch/blockFetcher.js +14 -8
- package/src/lib/blockFetch/blockFetcher.js.map +1 -1
- package/src/lib/blockFetch/fetchQueue.js +9 -7
- package/src/lib/blockFetch/fetchQueue.js.map +1 -1
- package/src/lib/blockFetch/httpBlockFetchTransport.js +2 -0
- package/src/lib/blockFetch/httpBlockFetchTransport.js.map +1 -1
- package/src/lib/browserKeyring.js +5 -2
- package/src/lib/browserKeyring.js.map +1 -1
- package/src/lib/controllers/api/blocks.d.ts.map +1 -1
- package/src/lib/controllers/api/blocks.js +9 -3
- package/src/lib/controllers/api/blocks.js.map +1 -1
- package/src/lib/controllers/api/brighthub/connectionController.d.ts +80 -0
- package/src/lib/controllers/api/brighthub/connectionController.d.ts.map +1 -0
- package/src/lib/controllers/api/brighthub/connectionController.js +890 -0
- package/src/lib/controllers/api/brighthub/connectionController.js.map +1 -0
- package/src/lib/controllers/api/brighthub/index.d.ts +9 -0
- package/src/lib/controllers/api/brighthub/index.d.ts.map +1 -0
- package/src/lib/controllers/api/brighthub/index.js +12 -0
- package/src/lib/controllers/api/brighthub/index.js.map +1 -0
- package/src/lib/controllers/api/brighthub/messagingController.d.ts +84 -0
- package/src/lib/controllers/api/brighthub/messagingController.d.ts.map +1 -0
- package/src/lib/controllers/api/brighthub/messagingController.js +1077 -0
- package/src/lib/controllers/api/brighthub/messagingController.js.map +1 -0
- package/src/lib/controllers/api/brighthub/notificationController.d.ts +89 -0
- package/src/lib/controllers/api/brighthub/notificationController.d.ts.map +1 -0
- package/src/lib/controllers/api/brighthub/notificationController.js +444 -0
- package/src/lib/controllers/api/brighthub/notificationController.js.map +1 -0
- package/src/lib/controllers/api/brighthub/postController.d.ts +75 -0
- package/src/lib/controllers/api/brighthub/postController.d.ts.map +1 -0
- package/src/lib/controllers/api/brighthub/postController.js +388 -0
- package/src/lib/controllers/api/brighthub/postController.js.map +1 -0
- package/src/lib/controllers/api/brighthub/timelineController.d.ts +74 -0
- package/src/lib/controllers/api/brighthub/timelineController.d.ts.map +1 -0
- package/src/lib/controllers/api/brighthub/timelineController.js +418 -0
- package/src/lib/controllers/api/brighthub/timelineController.js.map +1 -0
- package/src/lib/controllers/api/brightpass.d.ts.map +1 -1
- package/src/lib/controllers/api/brightpass.js +46 -4
- package/src/lib/controllers/api/brightpass.js.map +1 -1
- package/src/lib/controllers/api/cbl.js +1 -0
- package/src/lib/controllers/api/cbl.js.map +1 -1
- package/src/lib/controllers/api/channels.js +2 -2
- package/src/lib/controllers/api/channels.js.map +1 -1
- package/src/lib/controllers/api/conversations.js +1 -1
- package/src/lib/controllers/api/conversations.js.map +1 -1
- package/src/lib/controllers/api/docs.js +2 -1
- package/src/lib/controllers/api/docs.js.map +1 -1
- package/src/lib/controllers/api/emails.d.ts.map +1 -1
- package/src/lib/controllers/api/emails.js +16 -2
- package/src/lib/controllers/api/emails.js.map +1 -1
- package/src/lib/controllers/api/explodingMessages.js +2 -4
- package/src/lib/controllers/api/explodingMessages.js.map +1 -1
- package/src/lib/controllers/api/groups.js +2 -2
- package/src/lib/controllers/api/groups.js.map +1 -1
- package/src/lib/controllers/api/health.d.ts +9 -2
- package/src/lib/controllers/api/health.d.ts.map +1 -1
- package/src/lib/controllers/api/health.js +48 -6
- package/src/lib/controllers/api/health.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.js +2 -0
- package/src/lib/controllers/api/introspection.js.map +1 -1
- package/src/lib/controllers/api/messages.js +1 -1
- package/src/lib/controllers/api/messages.js.map +1 -1
- package/src/lib/controllers/api/nodes.js +6 -6
- package/src/lib/controllers/api/nodes.js.map +1 -1
- package/src/lib/controllers/api/quorum.d.ts +1 -1
- package/src/lib/controllers/api/quorum.d.ts.map +1 -1
- package/src/lib/controllers/api/quorum.js +3 -2
- package/src/lib/controllers/api/quorum.js.map +1 -1
- package/src/lib/controllers/api/scbl.js +3 -0
- package/src/lib/controllers/api/scbl.js.map +1 -1
- package/src/lib/controllers/api/sessions.d.ts +18 -2
- package/src/lib/controllers/api/sessions.d.ts.map +1 -1
- package/src/lib/controllers/api/sessions.js +60 -3
- package/src/lib/controllers/api/sessions.js.map +1 -1
- package/src/lib/controllers/api/sync.js +4 -4
- package/src/lib/controllers/api/sync.js.map +1 -1
- package/src/lib/controllers/api/user.d.ts +2 -0
- package/src/lib/controllers/api/user.d.ts.map +1 -1
- package/src/lib/controllers/api/user.js +95 -3
- package/src/lib/controllers/api/user.js.map +1 -1
- package/src/lib/controllers/identity/deviceController.js +2 -2
- package/src/lib/controllers/identity/deviceController.js.map +1 -1
- package/src/lib/controllers/identity/directoryController.js +1 -1
- package/src/lib/controllers/identity/directoryController.js.map +1 -1
- package/src/lib/controllers/identity/identityProofController.js +4 -6
- package/src/lib/controllers/identity/identityProofController.js.map +1 -1
- package/src/lib/databaseInit.d.ts +3 -3
- package/src/lib/databaseInit.js +5 -5
- package/src/lib/databaseInit.js.map +1 -1
- package/src/lib/datastore/block-document-store.d.ts.map +1 -1
- package/src/lib/datastore/block-document-store.js +18 -6
- package/src/lib/datastore/block-document-store.js.map +1 -1
- package/src/lib/datastore/document-store.d.ts.map +1 -1
- package/src/lib/datastore/memory-document-store.js +5 -2
- package/src/lib/datastore/memory-document-store.js.map +1 -1
- package/src/lib/encryption/encryptedMetadataService.js +2 -0
- package/src/lib/encryption/encryptedMetadataService.js.map +1 -1
- package/src/lib/encryption/encryptionAwareReplication.js +3 -0
- package/src/lib/encryption/encryptionAwareReplication.js.map +1 -1
- package/src/lib/encryption/errors.d.ts.map +1 -1
- package/src/lib/encryption/errors.js +8 -0
- package/src/lib/encryption/errors.js.map +1 -1
- package/src/lib/encryption/poolKeyManager.js +2 -0
- package/src/lib/encryption/poolKeyManager.js.map +1 -1
- package/src/lib/environment.js +10 -0
- package/src/lib/environment.js.map +1 -1
- package/src/lib/errors/express-validation.js +1 -0
- package/src/lib/errors/express-validation.js.map +1 -1
- package/src/lib/errors/invalid-backup-code-version.js +1 -0
- package/src/lib/errors/invalid-backup-code-version.js.map +1 -1
- package/src/lib/errors/memberIndexSchemaValidationError.js +1 -0
- package/src/lib/errors/memberIndexSchemaValidationError.js.map +1 -1
- package/src/lib/errors/missing-validated-data.js +2 -0
- package/src/lib/errors/missing-validated-data.js.map +1 -1
- package/src/lib/errors/token-not-found.js +1 -0
- package/src/lib/errors/token-not-found.js.map +1 -1
- package/src/lib/errors/typed-error-local.js +3 -0
- package/src/lib/errors/typed-error-local.js.map +1 -1
- package/src/lib/interfaces/brightpass/index.d.ts +1 -1
- package/src/lib/interfaces/brightpass/index.d.ts.map +1 -1
- package/src/lib/interfaces/environment.d.ts +1 -1
- package/src/lib/interfaces/environment.d.ts.map +1 -1
- package/src/lib/interfaces/member/memberProfileResponse.d.ts.map +1 -1
- package/src/lib/interfaces/member/operational.d.ts.map +1 -1
- package/src/lib/interfaces/member-init-config.d.ts +1 -1
- package/src/lib/interfaces/member-init-config.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-backup-codes-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-challenge-response.d.ts.map +1 -1
- 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.map +1 -1
- package/src/lib/interfaces/responses/api-discover-block-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-express-validation-error.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-get-block-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-get-node-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-health-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-list-nodes-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-login-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-members-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-mnemonic-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-reconcile-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-register-node-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-registration-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-replicate-block-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-request-user-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-store-block-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-store-cbl-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/api-sync-request-response.d.ts.map +1 -1
- package/src/lib/interfaces/responses/brighthub/api-connection-response.d.ts +21 -0
- package/src/lib/interfaces/responses/brighthub/api-connection-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/brighthub/api-connection-response.js +3 -0
- package/src/lib/interfaces/responses/brighthub/api-connection-response.js.map +1 -0
- package/src/lib/interfaces/responses/brighthub/api-messaging-response.d.ts +39 -0
- package/src/lib/interfaces/responses/brighthub/api-messaging-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/brighthub/api-messaging-response.js +3 -0
- package/src/lib/interfaces/responses/brighthub/api-messaging-response.js.map +1 -0
- package/src/lib/interfaces/responses/brighthub/api-notification-response.d.ts +30 -0
- package/src/lib/interfaces/responses/brighthub/api-notification-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/brighthub/api-notification-response.js +3 -0
- package/src/lib/interfaces/responses/brighthub/api-notification-response.js.map +1 -0
- package/src/lib/interfaces/responses/brighthub/api-post-response.d.ts +21 -0
- package/src/lib/interfaces/responses/brighthub/api-post-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/brighthub/api-post-response.js +3 -0
- package/src/lib/interfaces/responses/brighthub/api-post-response.js.map +1 -0
- package/src/lib/interfaces/responses/brighthub/api-timeline-response.d.ts +14 -0
- package/src/lib/interfaces/responses/brighthub/api-timeline-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/brighthub/api-timeline-response.js +3 -0
- package/src/lib/interfaces/responses/brighthub/api-timeline-response.js.map +1 -0
- package/src/lib/interfaces/responses/brighthub/api-user-profile-response.d.ts +10 -0
- package/src/lib/interfaces/responses/brighthub/api-user-profile-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/brighthub/api-user-profile-response.js +3 -0
- package/src/lib/interfaces/responses/brighthub/api-user-profile-response.js.map +1 -0
- package/src/lib/interfaces/responses/brighthub/index.d.ts +13 -0
- package/src/lib/interfaces/responses/brighthub/index.d.ts.map +1 -0
- package/src/lib/interfaces/responses/brighthub/index.js +9 -0
- package/src/lib/interfaces/responses/brighthub/index.js.map +1 -0
- package/src/lib/interfaces/responses/index.d.ts +1 -0
- package/src/lib/interfaces/responses/index.d.ts.map +1 -1
- package/src/lib/interfaces/storage/storedDocumentTypes.d.ts +1 -1
- package/src/lib/interfaces/storage/storedDocumentTypes.js +1 -1
- package/src/lib/interfaces/storage/userRoleSchema.d.ts.map +1 -1
- package/src/lib/interfaces/storage/userRoleSchema.js +1 -3
- package/src/lib/interfaces/storage/userRoleSchema.js.map +1 -1
- package/src/lib/middlewares.js +31 -31
- package/src/lib/middlewares.js.map +1 -1
- package/src/lib/nodeKeyring.js +2 -0
- package/src/lib/nodeKeyring.js.map +1 -1
- package/src/lib/plugins/brightchain-database-plugin.d.ts +14 -14
- package/src/lib/plugins/brightchain-database-plugin.d.ts.map +1 -1
- package/src/lib/plugins/brightchain-database-plugin.js +36 -34
- package/src/lib/plugins/brightchain-database-plugin.js.map +1 -1
- package/src/lib/routers/api.d.ts +62 -1
- package/src/lib/routers/api.d.ts.map +1 -1
- package/src/lib/routers/api.js +123 -2
- package/src/lib/routers/api.js.map +1 -1
- package/src/lib/routers/app.d.ts.map +1 -1
- package/src/lib/routers/app.js +10 -1
- package/src/lib/routers/app.js.map +1 -1
- package/src/lib/routers/base.js +2 -0
- package/src/lib/routers/base.js.map +1 -1
- package/src/lib/secureEnclaveKeyring.js +4 -2
- package/src/lib/secureEnclaveKeyring.js.map +1 -1
- package/src/lib/services/auth.d.ts.map +1 -1
- package/src/lib/services/auth.js +11 -2
- package/src/lib/services/auth.js.map +1 -1
- package/src/lib/services/base.js +1 -0
- package/src/lib/services/base.js.map +1 -1
- package/src/lib/services/blockServiceFactory.js +2 -0
- package/src/lib/services/blockServiceFactory.js.map +1 -1
- package/src/lib/services/blockStore.js +3 -2
- package/src/lib/services/blockStore.js.map +1 -1
- package/src/lib/services/blocks.js +1 -0
- package/src/lib/services/blocks.js.map +1 -1
- package/src/lib/services/brightChainBackupCodeService.d.ts +114 -0
- package/src/lib/services/brightChainBackupCodeService.d.ts.map +1 -0
- package/src/lib/services/brightChainBackupCodeService.js +303 -0
- package/src/lib/services/brightChainBackupCodeService.js.map +1 -0
- package/src/lib/services/brightchain-authentication-provider.d.ts.map +1 -1
- package/src/lib/services/brightchain-authentication-provider.js +40 -9
- package/src/lib/services/brightchain-authentication-provider.js.map +1 -1
- package/src/lib/services/brightchain-member-init.service.d.ts +17 -17
- package/src/lib/services/brightchain-member-init.service.d.ts.map +1 -1
- package/src/lib/services/brightchain-member-init.service.js +12 -9
- package/src/lib/services/brightchain-member-init.service.js.map +1 -1
- package/src/lib/services/brighthub/connectionService.d.ts +286 -0
- package/src/lib/services/brighthub/connectionService.d.ts.map +1 -0
- package/src/lib/services/brighthub/connectionService.js +1887 -0
- package/src/lib/services/brighthub/connectionService.js.map +1 -0
- package/src/lib/services/brighthub/discoveryService.d.ts +110 -0
- package/src/lib/services/brighthub/discoveryService.d.ts.map +1 -0
- package/src/lib/services/brighthub/discoveryService.js +528 -0
- package/src/lib/services/brighthub/discoveryService.js.map +1 -0
- package/src/lib/services/brighthub/feedService.d.ts +141 -0
- package/src/lib/services/brighthub/feedService.d.ts.map +1 -0
- package/src/lib/services/brighthub/feedService.js +418 -0
- package/src/lib/services/brighthub/feedService.js.map +1 -0
- package/src/lib/services/brighthub/index.d.ts +11 -0
- package/src/lib/services/brighthub/index.d.ts.map +1 -0
- package/src/lib/services/brighthub/index.js +14 -0
- package/src/lib/services/brighthub/index.js.map +1 -0
- package/src/lib/services/brighthub/messagingService.d.ts +109 -0
- package/src/lib/services/brighthub/messagingService.d.ts.map +1 -0
- package/src/lib/services/brighthub/messagingService.js +947 -0
- package/src/lib/services/brighthub/messagingService.js.map +1 -0
- package/src/lib/services/brighthub/messagingService.test-helpers.d.ts +75 -0
- package/src/lib/services/brighthub/messagingService.test-helpers.d.ts.map +1 -0
- package/src/lib/services/brighthub/messagingService.test-helpers.js +237 -0
- package/src/lib/services/brighthub/messagingService.test-helpers.js.map +1 -0
- package/src/lib/services/brighthub/notificationService.d.ts +172 -0
- package/src/lib/services/brighthub/notificationService.d.ts.map +1 -0
- package/src/lib/services/brighthub/notificationService.js +768 -0
- package/src/lib/services/brighthub/notificationService.js.map +1 -0
- package/src/lib/services/brighthub/notificationService.test-helpers.d.ts +75 -0
- package/src/lib/services/brighthub/notificationService.test-helpers.d.ts.map +1 -0
- package/src/lib/services/brighthub/notificationService.test-helpers.js +230 -0
- package/src/lib/services/brighthub/notificationService.test-helpers.js.map +1 -0
- package/src/lib/services/brighthub/postService.d.ts +129 -0
- package/src/lib/services/brighthub/postService.d.ts.map +1 -0
- package/src/lib/services/brighthub/postService.js +470 -0
- package/src/lib/services/brighthub/postService.js.map +1 -0
- package/src/lib/services/brighthub/postService.test-helpers.d.ts +40 -0
- package/src/lib/services/brighthub/postService.test-helpers.d.ts.map +1 -0
- package/src/lib/services/brighthub/postService.test-helpers.js +84 -0
- package/src/lib/services/brighthub/postService.test-helpers.js.map +1 -0
- package/src/lib/services/brighthub/textFormatter.d.ts +64 -0
- package/src/lib/services/brighthub/textFormatter.d.ts.map +1 -0
- package/src/lib/services/brighthub/textFormatter.js +256 -0
- package/src/lib/services/brighthub/textFormatter.js.map +1 -0
- package/src/lib/services/brighthub/threadService.d.ts +79 -0
- package/src/lib/services/brighthub/threadService.d.ts.map +1 -0
- package/src/lib/services/brighthub/threadService.js +246 -0
- package/src/lib/services/brighthub/threadService.js.map +1 -0
- package/src/lib/services/brighthub/userProfileService.d.ts +203 -0
- package/src/lib/services/brighthub/userProfileService.d.ts.map +1 -0
- package/src/lib/services/brighthub/userProfileService.js +868 -0
- package/src/lib/services/brighthub/userProfileService.js.map +1 -0
- package/src/lib/services/brighthub/userProfileService.test-helpers.d.ts +86 -0
- package/src/lib/services/brighthub/userProfileService.test-helpers.d.ts.map +1 -0
- package/src/lib/services/brighthub/userProfileService.test-helpers.js +169 -0
- package/src/lib/services/brighthub/userProfileService.test-helpers.js.map +1 -0
- package/src/lib/services/brighthub/webSocketServer.d.ts +68 -0
- package/src/lib/services/brighthub/webSocketServer.d.ts.map +1 -0
- package/src/lib/services/brighthub/webSocketServer.js +194 -0
- package/src/lib/services/brighthub/webSocketServer.js.map +1 -0
- package/src/lib/services/brightpass/auditLogger.js +10 -5
- package/src/lib/services/brightpass/auditLogger.js.map +1 -1
- package/src/lib/services/brightpass/vaultEncryption.js +8 -8
- package/src/lib/services/brightpass/vaultEncryption.js.map +1 -1
- package/src/lib/services/brightpass.js +16 -8
- package/src/lib/services/brightpass.js.map +1 -1
- package/src/lib/services/cliOperatorPrompt.js +5 -2
- package/src/lib/services/cliOperatorPrompt.js.map +1 -1
- package/src/lib/services/clientWebSocketServer.d.ts +69 -4
- package/src/lib/services/clientWebSocketServer.d.ts.map +1 -1
- package/src/lib/services/clientWebSocketServer.js +188 -10
- package/src/lib/services/clientWebSocketServer.js.map +1 -1
- package/src/lib/services/contentAwareBlocksService.js +2 -0
- package/src/lib/services/contentAwareBlocksService.js.map +1 -1
- package/src/lib/services/contentIngestionService.d.ts.map +1 -1
- package/src/lib/services/contentIngestionService.js +2 -0
- package/src/lib/services/contentIngestionService.js.map +1 -1
- package/src/lib/services/diskQuorumService.js +3 -0
- package/src/lib/services/diskQuorumService.js.map +1 -1
- package/src/lib/services/email.js +5 -0
- package/src/lib/services/email.js.map +1 -1
- package/src/lib/services/eventNotificationSystem.d.ts +51 -10
- package/src/lib/services/eventNotificationSystem.d.ts.map +1 -1
- package/src/lib/services/eventNotificationSystem.js +76 -23
- package/src/lib/services/eventNotificationSystem.js.map +1 -1
- package/src/lib/services/expirationScheduler.js +6 -3
- package/src/lib/services/expirationScheduler.js.map +1 -1
- package/src/lib/services/fakeEmailService.js +3 -4
- package/src/lib/services/fakeEmailService.js.map +1 -1
- package/src/lib/services/fec.js +1 -3
- package/src/lib/services/fec.js.map +1 -1
- package/src/lib/services/fecServiceFactory.js +2 -2
- package/src/lib/services/fecServiceFactory.js.map +1 -1
- package/src/lib/services/fecUsageExample.js +1 -3
- package/src/lib/services/fecUsageExample.js.map +1 -1
- package/src/lib/services/identityExpirationScheduler.d.ts.map +1 -1
- package/src/lib/services/identityExpirationScheduler.js +7 -2
- package/src/lib/services/identityExpirationScheduler.js.map +1 -1
- package/src/lib/services/index.d.ts +3 -2
- package/src/lib/services/index.d.ts.map +1 -1
- package/src/lib/services/index.js +3 -2
- package/src/lib/services/index.js.map +1 -1
- package/src/lib/services/messageEventsWebSocketHandler.js +1 -0
- package/src/lib/services/messageEventsWebSocketHandler.js.map +1 -1
- package/src/lib/services/messagePassingService.js +5 -0
- package/src/lib/services/messagePassingService.js.map +1 -1
- package/src/lib/services/nativeRsFecService.js +3 -5
- package/src/lib/services/nativeRsFecService.js.map +1 -1
- package/src/lib/services/presenceService.js +5 -4
- package/src/lib/services/presenceService.js.map +1 -1
- package/src/lib/services/quorum.js +3 -2
- package/src/lib/services/quorum.js.map +1 -1
- package/src/lib/services/quorumDatabaseAdapter.d.ts +5 -5
- package/src/lib/services/quorumDatabaseAdapter.d.ts.map +1 -1
- package/src/lib/services/quorumDatabaseAdapter.js +5 -3
- package/src/lib/services/quorumDatabaseAdapter.js.map +1 -1
- package/src/lib/services/rbac-input-builder.js +5 -0
- package/src/lib/services/rbac-input-builder.js.map +1 -1
- package/src/lib/services/secureKeyStorage.js +3 -0
- package/src/lib/services/secureKeyStorage.js.map +1 -1
- package/src/lib/services/sessionAdapter.d.ts +4 -4
- package/src/lib/services/sessionAdapter.d.ts.map +1 -1
- package/src/lib/services/sessionAdapter.js +3 -2
- package/src/lib/services/sessionAdapter.js.map +1 -1
- package/src/lib/services/webSocketMessageServer.js +7 -4
- package/src/lib/services/webSocketMessageServer.js.map +1 -1
- package/src/lib/services/webSocketPeerProvider.js +2 -1
- package/src/lib/services/webSocketPeerProvider.js.map +1 -1
- package/src/lib/services/websocketHandler.js +9 -1
- package/src/lib/services/websocketHandler.js.map +1 -1
- package/src/lib/shared-types.d.ts +1 -2
- package/src/lib/shared-types.d.ts.map +1 -1
- package/src/lib/stores/__tests__/helpers/mockCloudBlockStore.d.ts +63 -0
- package/src/lib/stores/__tests__/helpers/mockCloudBlockStore.d.ts.map +1 -0
- package/src/lib/stores/__tests__/helpers/mockCloudBlockStore.js +160 -0
- package/src/lib/stores/__tests__/helpers/mockCloudBlockStore.js.map +1 -0
- package/src/lib/stores/availabilityAwareBlockStore.js +34 -5
- package/src/lib/stores/availabilityAwareBlockStore.js.map +1 -1
- package/src/lib/stores/cloudBlockStoreBase.d.ts +121 -0
- package/src/lib/stores/cloudBlockStoreBase.d.ts.map +1 -0
- package/src/lib/stores/cloudBlockStoreBase.js +1165 -0
- package/src/lib/stores/cloudBlockStoreBase.js.map +1 -0
- package/src/lib/stores/diskBlockAsyncStore.js +9 -5
- package/src/lib/stores/diskBlockAsyncStore.js.map +1 -1
- package/src/lib/stores/diskBlockMetadataStore.js +2 -0
- package/src/lib/stores/diskBlockMetadataStore.js.map +1 -1
- package/src/lib/stores/diskBlockStore.js +10 -8
- package/src/lib/stores/diskBlockStore.js.map +1 -1
- package/src/lib/stores/diskCBLStore.d.ts.map +1 -1
- package/src/lib/stores/diskCBLStore.js +8 -0
- package/src/lib/stores/diskCBLStore.js.map +1 -1
- package/src/lib/stores/index.d.ts +1 -0
- package/src/lib/stores/index.d.ts.map +1 -1
- package/src/lib/stores/index.js +1 -0
- package/src/lib/stores/index.js.map +1 -1
- package/src/lib/systemKeyring.d.ts.map +1 -1
- package/src/lib/systemKeyring.js +5 -4
- package/src/lib/systemKeyring.js.map +1 -1
- package/src/lib/transforms/checksumTransform.js +1 -0
- package/src/lib/transforms/checksumTransform.js.map +1 -1
- package/src/lib/transforms/memoryWritableStream.js +1 -0
- package/src/lib/transforms/memoryWritableStream.js.map +1 -1
- package/src/lib/transforms/xorMultipleTransform.js +3 -0
- package/src/lib/transforms/xorMultipleTransform.js.map +1 -1
- package/src/lib/utils/rehydration.d.ts +1 -1
- package/src/lib/utils/rehydration.js +1 -1
- package/src/lib/utils/serialization.d.ts +1 -1
- package/src/lib/utils/serialization.js +1 -1
- package/src/lib/services/backupCodeService.d.ts +0 -35
- package/src/lib/services/backupCodeService.d.ts.map +0 -1
- package/src/lib/services/backupCodeService.js +0 -109
- package/src/lib/services/backupCodeService.js.map +0 -1
|
@@ -0,0 +1,1165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CloudBlockStoreBase = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* CloudBlockStoreBase - Abstract base class for cloud-backed block stores.
|
|
6
|
+
*
|
|
7
|
+
* Implements IBlockStore and IPooledBlockStore, encapsulating all shared cloud
|
|
8
|
+
* store logic (metadata serialization, FEC orchestration, CBL whitening, pool
|
|
9
|
+
* key management, retry logic). Subclasses implement only the cloud-specific
|
|
10
|
+
* I/O primitives (uploadObject, downloadObject, deleteObject, objectExists,
|
|
11
|
+
* listObjects, isTransientError).
|
|
12
|
+
*
|
|
13
|
+
* @see DiskBlockAsyncStore for the disk-based reference implementation
|
|
14
|
+
* @see AzureBlobBlockStore for the Azure Blob Storage subclass
|
|
15
|
+
* @see S3BlockStore for the Amazon S3 subclass
|
|
16
|
+
*/
|
|
17
|
+
const brightchain_lib_1 = require("@brightchain/brightchain-lib");
|
|
18
|
+
/**
|
|
19
|
+
* Cast a raw hex string to BlockId without validation.
|
|
20
|
+
* Used for opaque storage keys that must satisfy the branded type.
|
|
21
|
+
*/
|
|
22
|
+
function toStorageKey(hex) {
|
|
23
|
+
return hex;
|
|
24
|
+
}
|
|
25
|
+
/** Default TTL for the local checksum index (5 minutes) */
|
|
26
|
+
const DEFAULT_INDEX_TTL_MS = 5 * 60 * 1000;
|
|
27
|
+
/** Default page size for listing objects during index refresh */
|
|
28
|
+
const DEFAULT_LIST_PAGE_SIZE = 1000;
|
|
29
|
+
class CloudBlockStoreBase {
|
|
30
|
+
config;
|
|
31
|
+
_blockSize;
|
|
32
|
+
fecService = null;
|
|
33
|
+
// === Local checksum index for getRandomBlocks ===
|
|
34
|
+
localIndex = new Set();
|
|
35
|
+
indexStale = true;
|
|
36
|
+
indexLastRefreshed = 0;
|
|
37
|
+
indexTtlMs;
|
|
38
|
+
listPageSize;
|
|
39
|
+
constructor(config, indexTtlMs = DEFAULT_INDEX_TTL_MS, listPageSize = DEFAULT_LIST_PAGE_SIZE) {
|
|
40
|
+
this.config = config;
|
|
41
|
+
this._blockSize = config.blockSize;
|
|
42
|
+
this.indexTtlMs = indexTtlMs;
|
|
43
|
+
this.listPageSize = listPageSize;
|
|
44
|
+
}
|
|
45
|
+
// =========================================================================
|
|
46
|
+
// Public accessors
|
|
47
|
+
// =========================================================================
|
|
48
|
+
get blockSize() {
|
|
49
|
+
return this._blockSize;
|
|
50
|
+
}
|
|
51
|
+
setFecService(fecService) {
|
|
52
|
+
this.fecService = fecService;
|
|
53
|
+
}
|
|
54
|
+
getFecService() {
|
|
55
|
+
return this.fecService;
|
|
56
|
+
}
|
|
57
|
+
// =========================================================================
|
|
58
|
+
// Key management
|
|
59
|
+
// =========================================================================
|
|
60
|
+
/**
|
|
61
|
+
* Build the object key for block data.
|
|
62
|
+
* Pattern: {keyPrefix}{poolId}/{checksumHex}
|
|
63
|
+
*/
|
|
64
|
+
buildObjectKey(checksumHex, poolId = brightchain_lib_1.DEFAULT_POOL) {
|
|
65
|
+
const prefix = this.config.keyPrefix ?? '';
|
|
66
|
+
return `${prefix}${poolId}/${checksumHex}`;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Build the object key for a metadata sidecar.
|
|
70
|
+
* Pattern: {keyPrefix}{poolId}/{checksumHex}.meta
|
|
71
|
+
*/
|
|
72
|
+
buildMetaKey(checksumHex, poolId = brightchain_lib_1.DEFAULT_POOL) {
|
|
73
|
+
return `${this.buildObjectKey(checksumHex, poolId)}.meta`;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Build the object key for a parity block.
|
|
77
|
+
* Pattern: {keyPrefix}{poolId}/parity/{checksumHex}/{parityIndex}
|
|
78
|
+
*/
|
|
79
|
+
buildParityKey(checksumHex, parityIndex, poolId = brightchain_lib_1.DEFAULT_POOL) {
|
|
80
|
+
const prefix = this.config.keyPrefix ?? '';
|
|
81
|
+
return `${prefix}${poolId}/parity/${checksumHex}/${parityIndex}`;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Build the prefix for listing parity blocks of a given data block.
|
|
85
|
+
*/
|
|
86
|
+
buildParityPrefix(checksumHex, poolId = brightchain_lib_1.DEFAULT_POOL) {
|
|
87
|
+
const prefix = this.config.keyPrefix ?? '';
|
|
88
|
+
return `${prefix}${poolId}/parity/${checksumHex}/`;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Build the prefix for listing all blocks in a pool.
|
|
92
|
+
*/
|
|
93
|
+
buildPoolPrefix(poolId = brightchain_lib_1.DEFAULT_POOL) {
|
|
94
|
+
const prefix = this.config.keyPrefix ?? '';
|
|
95
|
+
return `${prefix}${poolId}/`;
|
|
96
|
+
}
|
|
97
|
+
// =========================================================================
|
|
98
|
+
// Utility helpers
|
|
99
|
+
// =========================================================================
|
|
100
|
+
keyToHex(key) {
|
|
101
|
+
return typeof key === 'string' ? key : key.toHex();
|
|
102
|
+
}
|
|
103
|
+
hexToChecksum(hex) {
|
|
104
|
+
return brightchain_lib_1.Checksum.fromHex(hex);
|
|
105
|
+
}
|
|
106
|
+
// =========================================================================
|
|
107
|
+
// Retry logic
|
|
108
|
+
// =========================================================================
|
|
109
|
+
/**
|
|
110
|
+
* Retry an operation with exponential backoff for transient errors.
|
|
111
|
+
* Base delay 1s, factor 2x, max 3 retries by default.
|
|
112
|
+
*/
|
|
113
|
+
async withRetry(operation, blockChecksum, fn, maxRetries = 3) {
|
|
114
|
+
let lastError;
|
|
115
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
116
|
+
try {
|
|
117
|
+
return await fn();
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
lastError = error;
|
|
121
|
+
if (!this.isTransientError(error) || attempt === maxRetries) {
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
const delay = Math.pow(2, attempt) * 1000;
|
|
125
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.CloudOperationFailed, undefined, {
|
|
129
|
+
operation,
|
|
130
|
+
blockChecksum,
|
|
131
|
+
originalError: String(lastError),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
// =========================================================================
|
|
135
|
+
// Metadata serialization helpers
|
|
136
|
+
// =========================================================================
|
|
137
|
+
serializeMetadata(metadata) {
|
|
138
|
+
const file = {
|
|
139
|
+
blockId: metadata.blockId,
|
|
140
|
+
createdAt: metadata.createdAt.toISOString(),
|
|
141
|
+
expiresAt: metadata.expiresAt?.toISOString() ?? null,
|
|
142
|
+
durabilityLevel: metadata.durabilityLevel,
|
|
143
|
+
parityBlockIds: [...metadata.parityBlockIds],
|
|
144
|
+
accessCount: metadata.accessCount,
|
|
145
|
+
lastAccessedAt: metadata.lastAccessedAt.toISOString(),
|
|
146
|
+
replicationStatus: metadata.replicationStatus,
|
|
147
|
+
targetReplicationFactor: metadata.targetReplicationFactor,
|
|
148
|
+
replicaNodeIds: [...metadata.replicaNodeIds],
|
|
149
|
+
size: metadata.size,
|
|
150
|
+
checksum: metadata.checksum,
|
|
151
|
+
...(metadata.poolId !== undefined ? { poolId: metadata.poolId } : {}),
|
|
152
|
+
};
|
|
153
|
+
return new TextEncoder().encode(JSON.stringify(file));
|
|
154
|
+
}
|
|
155
|
+
deserializeMetadata(data) {
|
|
156
|
+
const json = new TextDecoder().decode(data);
|
|
157
|
+
const file = JSON.parse(json);
|
|
158
|
+
return {
|
|
159
|
+
blockId: file.blockId,
|
|
160
|
+
createdAt: new Date(file.createdAt),
|
|
161
|
+
expiresAt: file.expiresAt ? new Date(file.expiresAt) : null,
|
|
162
|
+
durabilityLevel: file.durabilityLevel,
|
|
163
|
+
parityBlockIds: file.parityBlockIds,
|
|
164
|
+
accessCount: file.accessCount,
|
|
165
|
+
lastAccessedAt: new Date(file.lastAccessedAt),
|
|
166
|
+
replicationStatus: file.replicationStatus,
|
|
167
|
+
targetReplicationFactor: file.targetReplicationFactor,
|
|
168
|
+
replicaNodeIds: file.replicaNodeIds,
|
|
169
|
+
size: file.size,
|
|
170
|
+
checksum: file.checksum,
|
|
171
|
+
...(file.poolId !== undefined ? { poolId: file.poolId } : {}),
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
// =========================================================================
|
|
175
|
+
// Local checksum index management
|
|
176
|
+
// =========================================================================
|
|
177
|
+
/**
|
|
178
|
+
* Check if the local index needs refreshing based on TTL.
|
|
179
|
+
*/
|
|
180
|
+
isIndexStale() {
|
|
181
|
+
if (this.indexStale)
|
|
182
|
+
return true;
|
|
183
|
+
return Date.now() - this.indexLastRefreshed > this.indexTtlMs;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Refresh the local checksum index by listing objects from the cloud store.
|
|
187
|
+
*/
|
|
188
|
+
async refreshIndex(poolId = brightchain_lib_1.DEFAULT_POOL) {
|
|
189
|
+
const prefix = this.buildPoolPrefix(poolId);
|
|
190
|
+
const keys = await this.listObjects(prefix, this.listPageSize);
|
|
191
|
+
this.localIndex.clear();
|
|
192
|
+
const poolPrefix = this.buildPoolPrefix(poolId);
|
|
193
|
+
for (const key of keys) {
|
|
194
|
+
// Extract checksum hex from key, skip .meta and parity/ keys
|
|
195
|
+
if (key.endsWith('.meta'))
|
|
196
|
+
continue;
|
|
197
|
+
if (key.includes('/parity/'))
|
|
198
|
+
continue;
|
|
199
|
+
const checksumHex = key.substring(poolPrefix.length);
|
|
200
|
+
if (checksumHex && !checksumHex.includes('/')) {
|
|
201
|
+
this.localIndex.add(checksumHex);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
this.indexStale = false;
|
|
205
|
+
this.indexLastRefreshed = Date.now();
|
|
206
|
+
}
|
|
207
|
+
// =========================================================================
|
|
208
|
+
// IBlockStore — Core Block Operations
|
|
209
|
+
// =========================================================================
|
|
210
|
+
async has(key) {
|
|
211
|
+
const hex = this.keyToHex(key);
|
|
212
|
+
const objectKey = this.buildObjectKey(hex);
|
|
213
|
+
return this.withRetry('has', hex, () => this.objectExists(objectKey));
|
|
214
|
+
}
|
|
215
|
+
async getData(key) {
|
|
216
|
+
const hex = this.keyToHex(key);
|
|
217
|
+
const objectKey = this.buildObjectKey(hex);
|
|
218
|
+
const data = await this.withRetry('getData', hex, () => this.downloadObject(objectKey));
|
|
219
|
+
// Record access in metadata
|
|
220
|
+
try {
|
|
221
|
+
const metaKey = this.buildMetaKey(hex);
|
|
222
|
+
if (await this.objectExists(metaKey)) {
|
|
223
|
+
const metaData = await this.downloadObject(metaKey);
|
|
224
|
+
const metadata = this.deserializeMetadata(metaData);
|
|
225
|
+
metadata.accessCount++;
|
|
226
|
+
metadata.lastAccessedAt = new Date();
|
|
227
|
+
await this.uploadObject(metaKey, this.serializeMetadata(metadata));
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
// Ignore metadata access errors — data retrieval is the priority
|
|
232
|
+
}
|
|
233
|
+
return new brightchain_lib_1.RawDataBlock(this._blockSize, data, new Date(), key, brightchain_lib_1.BlockType.RawData, brightchain_lib_1.BlockDataType.RawData, true, true);
|
|
234
|
+
}
|
|
235
|
+
async setData(block, options) {
|
|
236
|
+
const hex = this.keyToHex(block.idChecksum);
|
|
237
|
+
const objectKey = this.buildObjectKey(hex);
|
|
238
|
+
// Idempotent — skip if block already exists
|
|
239
|
+
const exists = await this.withRetry('setData.exists', hex, () => this.objectExists(objectKey));
|
|
240
|
+
if (exists)
|
|
241
|
+
return;
|
|
242
|
+
// Validate block
|
|
243
|
+
try {
|
|
244
|
+
block.validate();
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.BlockValidationFailed);
|
|
248
|
+
}
|
|
249
|
+
// Upload block data
|
|
250
|
+
await this.withRetry('setData.upload', hex, () => this.uploadObject(objectKey, block.data));
|
|
251
|
+
// Create and upload metadata sidecar
|
|
252
|
+
const metadata = (0, brightchain_lib_1.createDefaultBlockMetadata)(toStorageKey(hex), block.data.length, hex, options);
|
|
253
|
+
const metaKey = this.buildMetaKey(hex);
|
|
254
|
+
await this.withRetry('setData.meta', hex, () => this.uploadObject(metaKey, this.serializeMetadata(metadata)));
|
|
255
|
+
// Update local index
|
|
256
|
+
this.localIndex.add(hex);
|
|
257
|
+
// Generate parity blocks based on durability level
|
|
258
|
+
const durabilityLevel = options?.durabilityLevel ?? brightchain_lib_1.DurabilityLevel.Standard;
|
|
259
|
+
const parityCount = (0, brightchain_lib_1.getParityCountForDurability)(durabilityLevel);
|
|
260
|
+
if (parityCount > 0 && this.fecService) {
|
|
261
|
+
try {
|
|
262
|
+
await this.generateParityBlocks(block.idChecksum, parityCount);
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
// If parity generation fails, keep the block but without parity protection
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
async deleteData(key) {
|
|
270
|
+
const hex = this.keyToHex(key);
|
|
271
|
+
const objectKey = this.buildObjectKey(hex);
|
|
272
|
+
// Check existence
|
|
273
|
+
const exists = await this.withRetry('deleteData.exists', hex, () => this.objectExists(objectKey));
|
|
274
|
+
if (!exists) {
|
|
275
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.KeyNotFound, undefined, {
|
|
276
|
+
KEY: hex,
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
// Delete parity blocks first
|
|
280
|
+
try {
|
|
281
|
+
const parityPrefix = this.buildParityPrefix(hex);
|
|
282
|
+
const parityKeys = await this.listObjects(parityPrefix);
|
|
283
|
+
for (const pk of parityKeys) {
|
|
284
|
+
try {
|
|
285
|
+
await this.deleteObject(pk);
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
// Ignore errors deleting parity files
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
// Ignore errors listing parity blocks
|
|
294
|
+
}
|
|
295
|
+
// Delete block data
|
|
296
|
+
await this.withRetry('deleteData.delete', hex, () => this.deleteObject(objectKey));
|
|
297
|
+
// Delete metadata sidecar
|
|
298
|
+
try {
|
|
299
|
+
const metaKey = this.buildMetaKey(hex);
|
|
300
|
+
await this.deleteObject(metaKey);
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
// Ignore errors deleting metadata
|
|
304
|
+
}
|
|
305
|
+
// Update local index
|
|
306
|
+
this.localIndex.delete(hex);
|
|
307
|
+
}
|
|
308
|
+
async getRandomBlocks(count) {
|
|
309
|
+
if (count <= 0)
|
|
310
|
+
return [];
|
|
311
|
+
// Refresh index if stale
|
|
312
|
+
if (this.isIndexStale()) {
|
|
313
|
+
await this.refreshIndex();
|
|
314
|
+
}
|
|
315
|
+
const allChecksums = [...this.localIndex];
|
|
316
|
+
if (allChecksums.length === 0)
|
|
317
|
+
return [];
|
|
318
|
+
// Sample without replacement
|
|
319
|
+
const result = [];
|
|
320
|
+
const available = [...allChecksums];
|
|
321
|
+
const numToReturn = Math.min(count, available.length);
|
|
322
|
+
for (let i = 0; i < numToReturn; i++) {
|
|
323
|
+
const randomIndex = Math.floor(Math.random() * available.length);
|
|
324
|
+
result.push(this.hexToChecksum(available[randomIndex]));
|
|
325
|
+
available.splice(randomIndex, 1);
|
|
326
|
+
}
|
|
327
|
+
return result;
|
|
328
|
+
}
|
|
329
|
+
get(_key) {
|
|
330
|
+
// BlockHandle is synchronous but cloud operations are async.
|
|
331
|
+
// Cloud stores should use getData() for async access.
|
|
332
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.NotImplemented, undefined, {
|
|
333
|
+
ERROR: 'Synchronous get() is not supported for cloud stores. Use getData() instead.',
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
async put(key, data, options) {
|
|
337
|
+
const keyChecksum = typeof key === 'string' ? brightchain_lib_1.Checksum.fromHex(key) : key;
|
|
338
|
+
const block = new brightchain_lib_1.RawDataBlock(this._blockSize, data, new Date(), keyChecksum);
|
|
339
|
+
await this.setData(block, options);
|
|
340
|
+
}
|
|
341
|
+
async delete(key) {
|
|
342
|
+
const keyChecksum = typeof key === 'string' ? brightchain_lib_1.Checksum.fromHex(key) : key;
|
|
343
|
+
await this.deleteData(keyChecksum);
|
|
344
|
+
}
|
|
345
|
+
// =========================================================================
|
|
346
|
+
// IBlockStore — Metadata Operations
|
|
347
|
+
// =========================================================================
|
|
348
|
+
async getMetadata(key) {
|
|
349
|
+
const hex = this.keyToHex(key);
|
|
350
|
+
const metaKey = this.buildMetaKey(hex);
|
|
351
|
+
try {
|
|
352
|
+
const exists = await this.objectExists(metaKey);
|
|
353
|
+
if (!exists)
|
|
354
|
+
return null;
|
|
355
|
+
const data = await this.downloadObject(metaKey);
|
|
356
|
+
return this.deserializeMetadata(data);
|
|
357
|
+
}
|
|
358
|
+
catch {
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
async updateMetadata(key, updates) {
|
|
363
|
+
const hex = this.keyToHex(key);
|
|
364
|
+
const metaKey = this.buildMetaKey(hex);
|
|
365
|
+
const existing = await this.getMetadata(key);
|
|
366
|
+
if (!existing) {
|
|
367
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.KeyNotFound, undefined, {
|
|
368
|
+
KEY: hex,
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
const updated = { ...existing, ...updates };
|
|
372
|
+
await this.withRetry('updateMetadata', hex, () => this.uploadObject(metaKey, this.serializeMetadata(updated)));
|
|
373
|
+
}
|
|
374
|
+
// =========================================================================
|
|
375
|
+
// IBlockStore — FEC/Durability Operations
|
|
376
|
+
// =========================================================================
|
|
377
|
+
async generateParityBlocks(key, parityCount) {
|
|
378
|
+
const hex = this.keyToHex(key);
|
|
379
|
+
if (!this.fecService) {
|
|
380
|
+
throw new brightchain_lib_1.FecError(brightchain_lib_1.FecErrorType.FecEncodingFailed, undefined, {
|
|
381
|
+
ERROR: 'FEC service is not available',
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
const isAvailable = await this.fecService.isAvailable();
|
|
385
|
+
if (!isAvailable) {
|
|
386
|
+
throw new brightchain_lib_1.FecError(brightchain_lib_1.FecErrorType.FecEncodingFailed, undefined, {
|
|
387
|
+
ERROR: 'FEC service is not available in this environment',
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
// Download block data
|
|
391
|
+
const objectKey = this.buildObjectKey(hex);
|
|
392
|
+
const blockData = await this.withRetry('generateParity.download', hex, () => this.downloadObject(objectKey));
|
|
393
|
+
// Generate parity data
|
|
394
|
+
const parityData = await this.fecService.createParityData(blockData, parityCount);
|
|
395
|
+
// Store parity blocks as separate cloud objects
|
|
396
|
+
const parityBlockIds = [];
|
|
397
|
+
for (let i = 0; i < parityData.length; i++) {
|
|
398
|
+
const parityKey = this.buildParityKey(hex, i);
|
|
399
|
+
await this.withRetry('generateParity.upload', hex, () => this.uploadObject(parityKey, parityData[i].data));
|
|
400
|
+
const parityHex = `${hex}`.slice(0, 62) + i.toString(16).padStart(2, '0');
|
|
401
|
+
parityBlockIds.push((0, brightchain_lib_1.asBlockId)(parityHex));
|
|
402
|
+
}
|
|
403
|
+
// Update metadata with parity block IDs
|
|
404
|
+
try {
|
|
405
|
+
const existing = await this.getMetadata(key);
|
|
406
|
+
if (existing) {
|
|
407
|
+
await this.updateMetadata(key, { parityBlockIds });
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
catch {
|
|
411
|
+
// Ignore metadata update errors
|
|
412
|
+
}
|
|
413
|
+
return parityBlockIds.map((id) => {
|
|
414
|
+
const paddedHex = id.padEnd(64, '0').slice(0, 64);
|
|
415
|
+
return brightchain_lib_1.Checksum.fromHex(paddedHex);
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
async getParityBlocks(key) {
|
|
419
|
+
const metadata = await this.getMetadata(key);
|
|
420
|
+
if (!metadata)
|
|
421
|
+
return [];
|
|
422
|
+
return metadata.parityBlockIds.map((id) => {
|
|
423
|
+
const paddedHex = id.padEnd(128, '0').slice(0, 128);
|
|
424
|
+
return brightchain_lib_1.Checksum.fromHex(paddedHex);
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
async recoverBlock(key) {
|
|
428
|
+
const hex = this.keyToHex(key);
|
|
429
|
+
if (!this.fecService) {
|
|
430
|
+
return { success: false, error: 'FEC service is not available' };
|
|
431
|
+
}
|
|
432
|
+
const isAvailable = await this.fecService.isAvailable();
|
|
433
|
+
if (!isAvailable) {
|
|
434
|
+
return {
|
|
435
|
+
success: false,
|
|
436
|
+
error: 'FEC service is not available in this environment',
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
// Load parity data from cloud
|
|
440
|
+
const parityData = await this.loadParityData(hex);
|
|
441
|
+
if (parityData.length === 0) {
|
|
442
|
+
return { success: false, error: 'No parity data available for recovery' };
|
|
443
|
+
}
|
|
444
|
+
const metadata = await this.getMetadata(key);
|
|
445
|
+
if (!metadata) {
|
|
446
|
+
return { success: false, error: 'Block metadata not found' };
|
|
447
|
+
}
|
|
448
|
+
try {
|
|
449
|
+
// Try to get existing (possibly corrupted) data
|
|
450
|
+
let corruptedData = null;
|
|
451
|
+
try {
|
|
452
|
+
const objectKey = this.buildObjectKey(hex);
|
|
453
|
+
corruptedData = await this.downloadObject(objectKey);
|
|
454
|
+
}
|
|
455
|
+
catch {
|
|
456
|
+
// Block may be completely missing
|
|
457
|
+
}
|
|
458
|
+
const result = await this.fecService.recoverFileData(corruptedData, parityData, metadata.size);
|
|
459
|
+
if (result.recovered) {
|
|
460
|
+
const recoveredBlock = new brightchain_lib_1.RawDataBlock(this._blockSize, new Uint8Array(result.data));
|
|
461
|
+
// Re-upload the recovered block
|
|
462
|
+
const objectKey = this.buildObjectKey(hex);
|
|
463
|
+
await this.uploadObject(objectKey, new Uint8Array(result.data));
|
|
464
|
+
return { success: true, recoveredBlock };
|
|
465
|
+
}
|
|
466
|
+
return {
|
|
467
|
+
success: false,
|
|
468
|
+
error: 'Recovery failed - insufficient parity data',
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
catch (error) {
|
|
472
|
+
return {
|
|
473
|
+
success: false,
|
|
474
|
+
error: error instanceof Error ? error.message : 'Unknown recovery error',
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
async verifyBlockIntegrity(key) {
|
|
479
|
+
const hex = this.keyToHex(key);
|
|
480
|
+
if (!this.fecService) {
|
|
481
|
+
return this.has(key);
|
|
482
|
+
}
|
|
483
|
+
const isAvailable = await this.fecService.isAvailable();
|
|
484
|
+
if (!isAvailable) {
|
|
485
|
+
return this.has(key);
|
|
486
|
+
}
|
|
487
|
+
const objectKey = this.buildObjectKey(hex);
|
|
488
|
+
const exists = await this.objectExists(objectKey).catch(() => false);
|
|
489
|
+
if (!exists)
|
|
490
|
+
return false;
|
|
491
|
+
const parityData = await this.loadParityData(hex);
|
|
492
|
+
if (parityData.length === 0)
|
|
493
|
+
return true;
|
|
494
|
+
try {
|
|
495
|
+
const blockData = await this.downloadObject(objectKey);
|
|
496
|
+
return await this.fecService.verifyFileIntegrity(blockData, parityData);
|
|
497
|
+
}
|
|
498
|
+
catch {
|
|
499
|
+
return false;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Load parity data from cloud for a block.
|
|
504
|
+
*/
|
|
505
|
+
async loadParityData(checksumHex) {
|
|
506
|
+
const metadata = await this.getMetadata(checksumHex);
|
|
507
|
+
if (!metadata || metadata.parityBlockIds.length === 0)
|
|
508
|
+
return [];
|
|
509
|
+
const parityData = [];
|
|
510
|
+
for (let i = 0; i < metadata.parityBlockIds.length; i++) {
|
|
511
|
+
try {
|
|
512
|
+
const parityKey = this.buildParityKey(checksumHex, i);
|
|
513
|
+
const data = await this.downloadObject(parityKey);
|
|
514
|
+
parityData.push({ data, index: i });
|
|
515
|
+
}
|
|
516
|
+
catch {
|
|
517
|
+
// Skip missing parity blocks
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return parityData;
|
|
521
|
+
}
|
|
522
|
+
// =========================================================================
|
|
523
|
+
// IBlockStore — Replication Operations
|
|
524
|
+
// =========================================================================
|
|
525
|
+
async getBlocksPendingReplication() {
|
|
526
|
+
// Scan metadata for blocks with Pending status and targetReplicationFactor > 0
|
|
527
|
+
const prefix = this.buildPoolPrefix();
|
|
528
|
+
const keys = await this.listObjects(prefix);
|
|
529
|
+
const results = [];
|
|
530
|
+
for (const key of keys) {
|
|
531
|
+
if (!key.endsWith('.meta'))
|
|
532
|
+
continue;
|
|
533
|
+
try {
|
|
534
|
+
const data = await this.downloadObject(key);
|
|
535
|
+
const metadata = this.deserializeMetadata(data);
|
|
536
|
+
if (metadata.replicationStatus === brightchain_lib_1.ReplicationStatus.Pending &&
|
|
537
|
+
metadata.targetReplicationFactor > 0) {
|
|
538
|
+
results.push(this.hexToChecksum(metadata.checksum));
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
catch {
|
|
542
|
+
// Skip unreadable metadata
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
return results;
|
|
546
|
+
}
|
|
547
|
+
async getUnderReplicatedBlocks() {
|
|
548
|
+
const prefix = this.buildPoolPrefix();
|
|
549
|
+
const keys = await this.listObjects(prefix);
|
|
550
|
+
const results = [];
|
|
551
|
+
for (const key of keys) {
|
|
552
|
+
if (!key.endsWith('.meta'))
|
|
553
|
+
continue;
|
|
554
|
+
try {
|
|
555
|
+
const data = await this.downloadObject(key);
|
|
556
|
+
const metadata = this.deserializeMetadata(data);
|
|
557
|
+
if (metadata.replicationStatus === brightchain_lib_1.ReplicationStatus.UnderReplicated) {
|
|
558
|
+
results.push(this.hexToChecksum(metadata.checksum));
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
catch {
|
|
562
|
+
// Skip unreadable metadata
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
return results;
|
|
566
|
+
}
|
|
567
|
+
async recordReplication(key, nodeId) {
|
|
568
|
+
const hex = this.keyToHex(key);
|
|
569
|
+
const metadata = await this.getMetadata(key);
|
|
570
|
+
if (!metadata) {
|
|
571
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.KeyNotFound, undefined, {
|
|
572
|
+
KEY: hex,
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
const replicaNodeIds = [...metadata.replicaNodeIds];
|
|
576
|
+
if (!replicaNodeIds.includes(nodeId)) {
|
|
577
|
+
replicaNodeIds.push(nodeId);
|
|
578
|
+
}
|
|
579
|
+
let replicationStatus = metadata.replicationStatus;
|
|
580
|
+
if (replicaNodeIds.length >= metadata.targetReplicationFactor) {
|
|
581
|
+
replicationStatus = brightchain_lib_1.ReplicationStatus.Replicated;
|
|
582
|
+
}
|
|
583
|
+
else if (replicaNodeIds.length > 0) {
|
|
584
|
+
replicationStatus = brightchain_lib_1.ReplicationStatus.UnderReplicated;
|
|
585
|
+
}
|
|
586
|
+
await this.updateMetadata(key, { replicaNodeIds, replicationStatus });
|
|
587
|
+
}
|
|
588
|
+
async recordReplicaLoss(key, nodeId) {
|
|
589
|
+
const hex = this.keyToHex(key);
|
|
590
|
+
const metadata = await this.getMetadata(key);
|
|
591
|
+
if (!metadata) {
|
|
592
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.KeyNotFound, undefined, {
|
|
593
|
+
KEY: hex,
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
const replicaNodeIds = metadata.replicaNodeIds.filter((id) => id !== nodeId);
|
|
597
|
+
let replicationStatus = metadata.replicationStatus;
|
|
598
|
+
if (metadata.targetReplicationFactor > 0) {
|
|
599
|
+
if (replicaNodeIds.length >= metadata.targetReplicationFactor) {
|
|
600
|
+
replicationStatus = brightchain_lib_1.ReplicationStatus.Replicated;
|
|
601
|
+
}
|
|
602
|
+
else if (replicaNodeIds.length > 0) {
|
|
603
|
+
replicationStatus = brightchain_lib_1.ReplicationStatus.UnderReplicated;
|
|
604
|
+
}
|
|
605
|
+
else {
|
|
606
|
+
replicationStatus = brightchain_lib_1.ReplicationStatus.Pending;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
await this.updateMetadata(key, { replicaNodeIds, replicationStatus });
|
|
610
|
+
}
|
|
611
|
+
// =========================================================================
|
|
612
|
+
// IBlockStore — XOR Brightening Operations
|
|
613
|
+
// =========================================================================
|
|
614
|
+
async brightenBlock(key, randomBlockCount) {
|
|
615
|
+
const hex = this.keyToHex(key);
|
|
616
|
+
// Verify source block exists
|
|
617
|
+
const objectKey = this.buildObjectKey(hex);
|
|
618
|
+
const exists = await this.withRetry('brightenBlock.exists', hex, () => this.objectExists(objectKey));
|
|
619
|
+
if (!exists) {
|
|
620
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.KeyNotFound, undefined, {
|
|
621
|
+
KEY: hex,
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
// Get random blocks for XOR
|
|
625
|
+
const randomBlockChecksums = await this.getRandomBlocks(randomBlockCount);
|
|
626
|
+
if (randomBlockChecksums.length < randomBlockCount) {
|
|
627
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.InsufficientRandomBlocks, undefined, {
|
|
628
|
+
REQUESTED: randomBlockCount.toString(),
|
|
629
|
+
AVAILABLE: randomBlockChecksums.length.toString(),
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
// Download source block
|
|
633
|
+
const sourceData = await this.withRetry('brightenBlock.download', hex, () => this.downloadObject(objectKey));
|
|
634
|
+
// XOR with all random blocks
|
|
635
|
+
let result = new Uint8Array(sourceData);
|
|
636
|
+
for (const randomChecksum of randomBlockChecksums) {
|
|
637
|
+
const randomHex = randomChecksum.toHex();
|
|
638
|
+
const randomKey = this.buildObjectKey(randomHex);
|
|
639
|
+
const randomData = await this.withRetry('brightenBlock.downloadRandom', randomHex, () => this.downloadObject(randomKey));
|
|
640
|
+
result = new Uint8Array((0, brightchain_lib_1.xorArrays)(result, randomData));
|
|
641
|
+
}
|
|
642
|
+
// Store the brightened block
|
|
643
|
+
const brightenedBlock = new brightchain_lib_1.RawDataBlock(this._blockSize, new Uint8Array(result));
|
|
644
|
+
const brightenedHex = brightenedBlock.idChecksum.toHex();
|
|
645
|
+
const brightenedExists = await this.has(brightenedBlock.idChecksum);
|
|
646
|
+
if (!brightenedExists) {
|
|
647
|
+
await this.setData(brightenedBlock);
|
|
648
|
+
}
|
|
649
|
+
const randomBlockIds = randomBlockChecksums.map((c) => toStorageKey(c.toHex()));
|
|
650
|
+
return {
|
|
651
|
+
brightenedBlockId: toStorageKey(brightenedHex),
|
|
652
|
+
randomBlockIds,
|
|
653
|
+
originalBlockId: toStorageKey(hex),
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
// =========================================================================
|
|
657
|
+
// IBlockStore — CBL Whitening Operations
|
|
658
|
+
// =========================================================================
|
|
659
|
+
async storeCBLWithWhitening(cblData, options) {
|
|
660
|
+
if (!cblData || cblData.length === 0) {
|
|
661
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.BlockValidationFailed, undefined, {
|
|
662
|
+
ERROR: 'CBL data cannot be empty',
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
// Pad CBL to block size (includes length prefix)
|
|
666
|
+
const paddedCbl = (0, brightchain_lib_1.padToBlockSize)(cblData, this._blockSize);
|
|
667
|
+
if (paddedCbl.length > this._blockSize) {
|
|
668
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.BlockValidationFailed, undefined, {
|
|
669
|
+
ERROR: `CBL data too large: padded size (${paddedCbl.length}) exceeds block size (${this._blockSize}).`,
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
// Select or generate randomizer block
|
|
673
|
+
const randomBlock = await this.selectOrGenerateRandomizer(paddedCbl.length);
|
|
674
|
+
// XOR to create second block
|
|
675
|
+
const xorResult = (0, brightchain_lib_1.xorArrays)(paddedCbl, randomBlock);
|
|
676
|
+
let block1Stored = false;
|
|
677
|
+
let block1Id = toStorageKey('0'.repeat(64));
|
|
678
|
+
try {
|
|
679
|
+
// Store first block (randomizer)
|
|
680
|
+
const block1 = new brightchain_lib_1.RawDataBlock(this._blockSize, randomBlock);
|
|
681
|
+
if (!(await this.has(block1.idChecksum))) {
|
|
682
|
+
await this.setData(block1, options);
|
|
683
|
+
block1Stored = true;
|
|
684
|
+
}
|
|
685
|
+
block1Id = toStorageKey(block1.idChecksum.toHex());
|
|
686
|
+
// Store second block (CBL XOR R)
|
|
687
|
+
const block2 = new brightchain_lib_1.RawDataBlock(this._blockSize, xorResult);
|
|
688
|
+
await this.setData(block2, options);
|
|
689
|
+
const block2Id = toStorageKey(block2.idChecksum.toHex());
|
|
690
|
+
// Get parity block IDs if FEC redundancy was applied
|
|
691
|
+
let block1ParityIds;
|
|
692
|
+
let block2ParityIds;
|
|
693
|
+
const block1Meta = await this.getMetadata(block1Id);
|
|
694
|
+
if (block1Meta?.parityBlockIds?.length) {
|
|
695
|
+
block1ParityIds = block1Meta.parityBlockIds;
|
|
696
|
+
}
|
|
697
|
+
const block2Meta = await this.getMetadata(block2Id);
|
|
698
|
+
if (block2Meta?.parityBlockIds?.length) {
|
|
699
|
+
block2ParityIds = block2Meta.parityBlockIds;
|
|
700
|
+
}
|
|
701
|
+
const magnetUrl = this.generateCBLMagnetUrl(block1Id, block2Id, this._blockSize, block1ParityIds, block2ParityIds, options?.isEncrypted);
|
|
702
|
+
return {
|
|
703
|
+
blockId1: block1Id,
|
|
704
|
+
blockId2: block2Id,
|
|
705
|
+
blockSize: this._blockSize,
|
|
706
|
+
magnetUrl,
|
|
707
|
+
block1ParityIds,
|
|
708
|
+
block2ParityIds,
|
|
709
|
+
isEncrypted: options?.isEncrypted,
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
catch (error) {
|
|
713
|
+
// Rollback: delete block1 if it was stored by us
|
|
714
|
+
if (block1Stored && block1Id) {
|
|
715
|
+
try {
|
|
716
|
+
await this.deleteData(this.hexToChecksum(block1Id));
|
|
717
|
+
}
|
|
718
|
+
catch {
|
|
719
|
+
// Ignore rollback errors
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
throw error;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Select an existing block as a randomizer, or generate a new one.
|
|
727
|
+
*/
|
|
728
|
+
async selectOrGenerateRandomizer(size) {
|
|
729
|
+
try {
|
|
730
|
+
const randomBlocks = await this.getRandomBlocks(1);
|
|
731
|
+
if (randomBlocks.length > 0) {
|
|
732
|
+
const block = await this.getData(randomBlocks[0]);
|
|
733
|
+
if (block && block.data.length >= size) {
|
|
734
|
+
return block.data.slice(0, size);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
catch {
|
|
739
|
+
// Fall through to generation
|
|
740
|
+
}
|
|
741
|
+
return brightchain_lib_1.XorService.generateKey(size);
|
|
742
|
+
}
|
|
743
|
+
async retrieveCBL(blockId1, blockId2, block1ParityIds, block2ParityIds) {
|
|
744
|
+
// Retrieve first block (with recovery if needed)
|
|
745
|
+
const b1Checksum = typeof blockId1 === 'string' ? this.hexToChecksum(blockId1) : blockId1;
|
|
746
|
+
let block1Data;
|
|
747
|
+
try {
|
|
748
|
+
block1Data = await this.getData(b1Checksum);
|
|
749
|
+
}
|
|
750
|
+
catch (error) {
|
|
751
|
+
if (block1ParityIds?.length) {
|
|
752
|
+
const recovery = await this.recoverBlock(b1Checksum);
|
|
753
|
+
if (recovery.success && recovery.recoveredBlock) {
|
|
754
|
+
block1Data = recovery.recoveredBlock;
|
|
755
|
+
}
|
|
756
|
+
else {
|
|
757
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.KeyNotFound, undefined, {
|
|
758
|
+
KEY: this.keyToHex(blockId1),
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
else {
|
|
763
|
+
throw error;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
// Retrieve second block (with recovery if needed)
|
|
767
|
+
const b2Checksum = typeof blockId2 === 'string' ? this.hexToChecksum(blockId2) : blockId2;
|
|
768
|
+
let block2Data;
|
|
769
|
+
try {
|
|
770
|
+
block2Data = await this.getData(b2Checksum);
|
|
771
|
+
}
|
|
772
|
+
catch (error) {
|
|
773
|
+
if (block2ParityIds?.length) {
|
|
774
|
+
const recovery = await this.recoverBlock(b2Checksum);
|
|
775
|
+
if (recovery.success && recovery.recoveredBlock) {
|
|
776
|
+
block2Data = recovery.recoveredBlock;
|
|
777
|
+
}
|
|
778
|
+
else {
|
|
779
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.KeyNotFound, undefined, {
|
|
780
|
+
KEY: this.keyToHex(blockId2),
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
else {
|
|
785
|
+
throw error;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
// XOR to reconstruct padded CBL
|
|
789
|
+
const reconstructedPadded = (0, brightchain_lib_1.xorArrays)(block1Data.data, block2Data.data);
|
|
790
|
+
// Remove padding to get original CBL
|
|
791
|
+
return (0, brightchain_lib_1.unpadCblData)(reconstructedPadded);
|
|
792
|
+
}
|
|
793
|
+
parseCBLMagnetUrl(magnetUrl) {
|
|
794
|
+
if (!magnetUrl || !magnetUrl.startsWith('magnet:?')) {
|
|
795
|
+
throw new Error('Invalid magnet URL: must start with "magnet:?"');
|
|
796
|
+
}
|
|
797
|
+
const queryString = magnetUrl.substring('magnet:?'.length);
|
|
798
|
+
const params = new URLSearchParams(queryString);
|
|
799
|
+
const xt = params.get('xt');
|
|
800
|
+
if (xt !== 'urn:brightchain:cbl') {
|
|
801
|
+
throw new Error('Invalid magnet URL: xt parameter must be "urn:brightchain:cbl"');
|
|
802
|
+
}
|
|
803
|
+
const blockId1 = params.get('b1');
|
|
804
|
+
const blockId2 = params.get('b2');
|
|
805
|
+
const blockSizeStr = params.get('bs');
|
|
806
|
+
if (!blockId1)
|
|
807
|
+
throw new Error('Invalid magnet URL: missing b1 parameter');
|
|
808
|
+
if (!blockId2)
|
|
809
|
+
throw new Error('Invalid magnet URL: missing b2 parameter');
|
|
810
|
+
if (!blockSizeStr)
|
|
811
|
+
throw new Error('Invalid magnet URL: missing bs (block size) parameter');
|
|
812
|
+
const blockSize = parseInt(blockSizeStr, 10);
|
|
813
|
+
if (isNaN(blockSize) || blockSize <= 0) {
|
|
814
|
+
throw new Error('Invalid magnet URL: invalid block size');
|
|
815
|
+
}
|
|
816
|
+
const p1Param = params.get('p1');
|
|
817
|
+
const p2Param = params.get('p2');
|
|
818
|
+
const block1ParityIds = p1Param
|
|
819
|
+
? p1Param
|
|
820
|
+
.split(',')
|
|
821
|
+
.filter((id) => id)
|
|
822
|
+
.map(toStorageKey)
|
|
823
|
+
: undefined;
|
|
824
|
+
const block2ParityIds = p2Param
|
|
825
|
+
? p2Param
|
|
826
|
+
.split(',')
|
|
827
|
+
.filter((id) => id)
|
|
828
|
+
.map(toStorageKey)
|
|
829
|
+
: undefined;
|
|
830
|
+
const isEncrypted = params.get('enc') === '1';
|
|
831
|
+
return {
|
|
832
|
+
blockId1: toStorageKey(blockId1),
|
|
833
|
+
blockId2: toStorageKey(blockId2),
|
|
834
|
+
blockSize,
|
|
835
|
+
block1ParityIds,
|
|
836
|
+
block2ParityIds,
|
|
837
|
+
isEncrypted,
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
generateCBLMagnetUrl(blockId1, blockId2, blockSize, block1ParityIds, block2ParityIds, isEncrypted) {
|
|
841
|
+
const b1Id = typeof blockId1 === 'string' ? blockId1 : blockId1.toHex();
|
|
842
|
+
const b2Id = typeof blockId2 === 'string' ? blockId2 : blockId2.toHex();
|
|
843
|
+
const params = new URLSearchParams();
|
|
844
|
+
params.set('xt', 'urn:brightchain:cbl');
|
|
845
|
+
params.set('bs', blockSize.toString());
|
|
846
|
+
params.set('b1', b1Id);
|
|
847
|
+
params.set('b2', b2Id);
|
|
848
|
+
if (block1ParityIds?.length) {
|
|
849
|
+
params.set('p1', block1ParityIds.join(','));
|
|
850
|
+
}
|
|
851
|
+
if (block2ParityIds?.length) {
|
|
852
|
+
params.set('p2', block2ParityIds.join(','));
|
|
853
|
+
}
|
|
854
|
+
if (isEncrypted) {
|
|
855
|
+
params.set('enc', '1');
|
|
856
|
+
}
|
|
857
|
+
return `magnet:?${params.toString()}`;
|
|
858
|
+
}
|
|
859
|
+
// =========================================================================
|
|
860
|
+
// IPooledBlockStore — Pool-Scoped Block Operations
|
|
861
|
+
// =========================================================================
|
|
862
|
+
async hasInPool(pool, hash) {
|
|
863
|
+
(0, brightchain_lib_1.validatePoolId)(pool);
|
|
864
|
+
const objectKey = this.buildObjectKey(hash, pool);
|
|
865
|
+
return this.withRetry('hasInPool', hash, () => this.objectExists(objectKey));
|
|
866
|
+
}
|
|
867
|
+
async getFromPool(pool, hash) {
|
|
868
|
+
(0, brightchain_lib_1.validatePoolId)(pool);
|
|
869
|
+
const objectKey = this.buildObjectKey(hash, pool);
|
|
870
|
+
const data = await this.withRetry('getFromPool', hash, () => this.downloadObject(objectKey));
|
|
871
|
+
// Record access in metadata
|
|
872
|
+
try {
|
|
873
|
+
const metaKey = this.buildMetaKey(hash, pool);
|
|
874
|
+
if (await this.objectExists(metaKey)) {
|
|
875
|
+
const metaData = await this.downloadObject(metaKey);
|
|
876
|
+
const metadata = this.deserializeMetadata(metaData);
|
|
877
|
+
metadata.accessCount++;
|
|
878
|
+
metadata.lastAccessedAt = new Date();
|
|
879
|
+
await this.uploadObject(metaKey, this.serializeMetadata(metadata));
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
catch {
|
|
883
|
+
// Ignore metadata access errors
|
|
884
|
+
}
|
|
885
|
+
return data;
|
|
886
|
+
}
|
|
887
|
+
async putInPool(pool, data, options) {
|
|
888
|
+
(0, brightchain_lib_1.validatePoolId)(pool);
|
|
889
|
+
// Compute checksum for the data
|
|
890
|
+
const block = new brightchain_lib_1.RawDataBlock(this._blockSize, data);
|
|
891
|
+
const hash = block.idChecksum.toHex();
|
|
892
|
+
const objectKey = this.buildObjectKey(hash, pool);
|
|
893
|
+
// Idempotent — skip if already exists
|
|
894
|
+
const exists = await this.withRetry('putInPool.exists', hash, () => this.objectExists(objectKey));
|
|
895
|
+
if (exists)
|
|
896
|
+
return hash;
|
|
897
|
+
// Upload block data
|
|
898
|
+
await this.withRetry('putInPool.upload', hash, () => this.uploadObject(objectKey, data));
|
|
899
|
+
// Create and upload metadata sidecar
|
|
900
|
+
const metadata = (0, brightchain_lib_1.createDefaultBlockMetadata)(toStorageKey(hash), data.length, hash, options, pool);
|
|
901
|
+
const metaKey = this.buildMetaKey(hash, pool);
|
|
902
|
+
await this.withRetry('putInPool.meta', hash, () => this.uploadObject(metaKey, this.serializeMetadata(metadata)));
|
|
903
|
+
return hash;
|
|
904
|
+
}
|
|
905
|
+
async deleteFromPool(pool, hash) {
|
|
906
|
+
(0, brightchain_lib_1.validatePoolId)(pool);
|
|
907
|
+
const objectKey = this.buildObjectKey(hash, pool);
|
|
908
|
+
const exists = await this.withRetry('deleteFromPool.exists', hash, () => this.objectExists(objectKey));
|
|
909
|
+
if (!exists) {
|
|
910
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.KeyNotFound, undefined, {
|
|
911
|
+
KEY: hash,
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
// Delete parity blocks
|
|
915
|
+
try {
|
|
916
|
+
const parityPrefix = this.buildParityPrefix(hash, pool);
|
|
917
|
+
const parityKeys = await this.listObjects(parityPrefix);
|
|
918
|
+
for (const pk of parityKeys) {
|
|
919
|
+
try {
|
|
920
|
+
await this.deleteObject(pk);
|
|
921
|
+
}
|
|
922
|
+
catch {
|
|
923
|
+
// Ignore errors deleting parity files
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
catch {
|
|
928
|
+
// Ignore errors listing parity blocks
|
|
929
|
+
}
|
|
930
|
+
// Delete block data
|
|
931
|
+
await this.withRetry('deleteFromPool.delete', hash, () => this.deleteObject(objectKey));
|
|
932
|
+
// Delete metadata sidecar
|
|
933
|
+
try {
|
|
934
|
+
const metaKey = this.buildMetaKey(hash, pool);
|
|
935
|
+
await this.deleteObject(metaKey);
|
|
936
|
+
}
|
|
937
|
+
catch {
|
|
938
|
+
// Ignore errors deleting metadata
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
// =========================================================================
|
|
942
|
+
// IPooledBlockStore — Pool Management
|
|
943
|
+
// =========================================================================
|
|
944
|
+
async listPools() {
|
|
945
|
+
const prefix = this.config.keyPrefix ?? '';
|
|
946
|
+
const keys = await this.listObjects(prefix);
|
|
947
|
+
const pools = new Set();
|
|
948
|
+
for (const key of keys) {
|
|
949
|
+
// Strip the prefix and extract the pool segment (first path component)
|
|
950
|
+
const relative = key.substring(prefix.length);
|
|
951
|
+
const slashIndex = relative.indexOf('/');
|
|
952
|
+
if (slashIndex > 0) {
|
|
953
|
+
const poolId = relative.substring(0, slashIndex);
|
|
954
|
+
// Skip 'parity' segments that appear at pool level
|
|
955
|
+
if (poolId !== 'parity') {
|
|
956
|
+
pools.add(poolId);
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
return [...pools];
|
|
961
|
+
}
|
|
962
|
+
async *listBlocksInPool(pool, options) {
|
|
963
|
+
(0, brightchain_lib_1.validatePoolId)(pool);
|
|
964
|
+
const poolPrefix = this.buildPoolPrefix(pool);
|
|
965
|
+
const keys = await this.listObjects(poolPrefix);
|
|
966
|
+
const limit = options?.limit;
|
|
967
|
+
const cursor = options?.cursor;
|
|
968
|
+
let pastCursor = cursor === undefined;
|
|
969
|
+
let yielded = 0;
|
|
970
|
+
for (const key of keys) {
|
|
971
|
+
// Skip .meta and parity keys
|
|
972
|
+
if (key.endsWith('.meta'))
|
|
973
|
+
continue;
|
|
974
|
+
if (key.includes('/parity/'))
|
|
975
|
+
continue;
|
|
976
|
+
const hash = key.substring(poolPrefix.length);
|
|
977
|
+
if (!hash || hash.includes('/'))
|
|
978
|
+
continue;
|
|
979
|
+
if (!pastCursor) {
|
|
980
|
+
if (hash === cursor) {
|
|
981
|
+
pastCursor = true;
|
|
982
|
+
}
|
|
983
|
+
continue;
|
|
984
|
+
}
|
|
985
|
+
yield hash;
|
|
986
|
+
yielded++;
|
|
987
|
+
if (limit !== undefined && yielded >= limit) {
|
|
988
|
+
break;
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
async getPoolStats(pool) {
|
|
993
|
+
(0, brightchain_lib_1.validatePoolId)(pool);
|
|
994
|
+
const poolPrefix = this.buildPoolPrefix(pool);
|
|
995
|
+
const keys = await this.listObjects(poolPrefix);
|
|
996
|
+
let blockCount = 0;
|
|
997
|
+
let totalBytes = 0;
|
|
998
|
+
let earliestCreated = null;
|
|
999
|
+
let latestAccessed = null;
|
|
1000
|
+
for (const key of keys) {
|
|
1001
|
+
if (key.endsWith('.meta')) {
|
|
1002
|
+
try {
|
|
1003
|
+
const data = await this.downloadObject(key);
|
|
1004
|
+
const metadata = this.deserializeMetadata(data);
|
|
1005
|
+
blockCount++;
|
|
1006
|
+
totalBytes += metadata.size;
|
|
1007
|
+
if (!earliestCreated || metadata.createdAt < earliestCreated) {
|
|
1008
|
+
earliestCreated = metadata.createdAt;
|
|
1009
|
+
}
|
|
1010
|
+
if (!latestAccessed || metadata.lastAccessedAt > latestAccessed) {
|
|
1011
|
+
latestAccessed = metadata.lastAccessedAt;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
catch {
|
|
1015
|
+
// Skip unreadable metadata
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
const now = new Date();
|
|
1020
|
+
return {
|
|
1021
|
+
poolId: pool,
|
|
1022
|
+
blockCount,
|
|
1023
|
+
totalBytes,
|
|
1024
|
+
createdAt: earliestCreated ?? now,
|
|
1025
|
+
lastAccessedAt: latestAccessed ?? now,
|
|
1026
|
+
};
|
|
1027
|
+
}
|
|
1028
|
+
async deletePool(pool) {
|
|
1029
|
+
(0, brightchain_lib_1.validatePoolId)(pool);
|
|
1030
|
+
await this.performPoolDeletion(pool);
|
|
1031
|
+
}
|
|
1032
|
+
async performPoolDeletion(pool) {
|
|
1033
|
+
const poolPrefix = this.buildPoolPrefix(pool);
|
|
1034
|
+
const keys = await this.listObjects(poolPrefix);
|
|
1035
|
+
for (const key of keys) {
|
|
1036
|
+
try {
|
|
1037
|
+
await this.deleteObject(key);
|
|
1038
|
+
}
|
|
1039
|
+
catch {
|
|
1040
|
+
// Best-effort deletion
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
// =========================================================================
|
|
1045
|
+
// IPooledBlockStore — Pool-Scoped Whitening Operations
|
|
1046
|
+
// =========================================================================
|
|
1047
|
+
async getRandomBlocksFromPool(pool, count) {
|
|
1048
|
+
(0, brightchain_lib_1.validatePoolId)(pool);
|
|
1049
|
+
if (count <= 0)
|
|
1050
|
+
return [];
|
|
1051
|
+
const poolPrefix = this.buildPoolPrefix(pool);
|
|
1052
|
+
const keys = await this.listObjects(poolPrefix);
|
|
1053
|
+
// Collect block checksums (skip .meta and parity)
|
|
1054
|
+
const checksums = [];
|
|
1055
|
+
for (const key of keys) {
|
|
1056
|
+
if (key.endsWith('.meta'))
|
|
1057
|
+
continue;
|
|
1058
|
+
if (key.includes('/parity/'))
|
|
1059
|
+
continue;
|
|
1060
|
+
const hash = key.substring(poolPrefix.length);
|
|
1061
|
+
if (hash && !hash.includes('/')) {
|
|
1062
|
+
checksums.push(hash);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
if (checksums.length === 0)
|
|
1066
|
+
return [];
|
|
1067
|
+
// Sample without replacement
|
|
1068
|
+
const result = [];
|
|
1069
|
+
const available = [...checksums];
|
|
1070
|
+
const numToReturn = Math.min(count, available.length);
|
|
1071
|
+
for (let i = 0; i < numToReturn; i++) {
|
|
1072
|
+
const randomIndex = Math.floor(Math.random() * available.length);
|
|
1073
|
+
result.push(this.hexToChecksum(available[randomIndex]));
|
|
1074
|
+
available.splice(randomIndex, 1);
|
|
1075
|
+
}
|
|
1076
|
+
return result;
|
|
1077
|
+
}
|
|
1078
|
+
async bootstrapPool(pool, blockSize, count) {
|
|
1079
|
+
(0, brightchain_lib_1.validatePoolId)(pool);
|
|
1080
|
+
if (count <= 0)
|
|
1081
|
+
return;
|
|
1082
|
+
for (let i = 0; i < count; i++) {
|
|
1083
|
+
const data = brightchain_lib_1.XorService.generateKey(blockSize);
|
|
1084
|
+
await this.putInPool(pool, data);
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
async validatePoolDeletion(pool) {
|
|
1088
|
+
(0, brightchain_lib_1.validatePoolId)(pool);
|
|
1089
|
+
// For cloud stores, we do a simplified validation:
|
|
1090
|
+
// We don't have cross-pool CBL dependency tracking in the cloud,
|
|
1091
|
+
// so we return safe=true. Full CBL dependency checking would require
|
|
1092
|
+
// scanning all pools' blocks for CBL references, which is expensive.
|
|
1093
|
+
return {
|
|
1094
|
+
safe: true,
|
|
1095
|
+
dependentPools: [],
|
|
1096
|
+
referencedBlocks: [],
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
async forceDeletePool(pool) {
|
|
1100
|
+
(0, brightchain_lib_1.validatePoolId)(pool);
|
|
1101
|
+
await this.performPoolDeletion(pool);
|
|
1102
|
+
}
|
|
1103
|
+
// =========================================================================
|
|
1104
|
+
// IPooledBlockStore — Pool-Scoped CBL Whitening Operations
|
|
1105
|
+
// =========================================================================
|
|
1106
|
+
async storeCBLWithWhiteningInPool(pool, cblData, options) {
|
|
1107
|
+
(0, brightchain_lib_1.validatePoolId)(pool);
|
|
1108
|
+
if (!cblData || cblData.length === 0) {
|
|
1109
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.BlockValidationFailed, undefined, {
|
|
1110
|
+
ERROR: 'CBL data cannot be empty',
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
const paddedCbl = (0, brightchain_lib_1.padToBlockSize)(cblData, this._blockSize);
|
|
1114
|
+
if (paddedCbl.length > this._blockSize) {
|
|
1115
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.BlockValidationFailed, undefined, {
|
|
1116
|
+
ERROR: `CBL data too large: padded size (${paddedCbl.length}) exceeds block size (${this._blockSize}).`,
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1119
|
+
// Generate randomizer
|
|
1120
|
+
let randomBlock;
|
|
1121
|
+
try {
|
|
1122
|
+
const poolRandomBlocks = await this.getRandomBlocksFromPool(pool, 1);
|
|
1123
|
+
if (poolRandomBlocks.length > 0) {
|
|
1124
|
+
const blockData = await this.getFromPool(pool, poolRandomBlocks[0].toHex());
|
|
1125
|
+
if (blockData.length >= paddedCbl.length) {
|
|
1126
|
+
randomBlock = blockData.slice(0, paddedCbl.length);
|
|
1127
|
+
}
|
|
1128
|
+
else {
|
|
1129
|
+
randomBlock = brightchain_lib_1.XorService.generateKey(paddedCbl.length);
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
else {
|
|
1133
|
+
randomBlock = brightchain_lib_1.XorService.generateKey(paddedCbl.length);
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
catch {
|
|
1137
|
+
randomBlock = brightchain_lib_1.XorService.generateKey(paddedCbl.length);
|
|
1138
|
+
}
|
|
1139
|
+
const xorResult = (0, brightchain_lib_1.xorArrays)(paddedCbl, randomBlock);
|
|
1140
|
+
// Store both blocks in the pool
|
|
1141
|
+
const block1Hash = await this.putInPool(pool, randomBlock, options);
|
|
1142
|
+
const block2Hash = await this.putInPool(pool, xorResult, options);
|
|
1143
|
+
const block1Id = toStorageKey(block1Hash);
|
|
1144
|
+
const block2Id = toStorageKey(block2Hash);
|
|
1145
|
+
const magnetUrl = this.generateCBLMagnetUrl(block1Id, block2Id, this._blockSize, undefined, undefined, options?.isEncrypted);
|
|
1146
|
+
return {
|
|
1147
|
+
blockId1: block1Id,
|
|
1148
|
+
blockId2: block2Id,
|
|
1149
|
+
blockSize: this._blockSize,
|
|
1150
|
+
magnetUrl,
|
|
1151
|
+
isEncrypted: options?.isEncrypted,
|
|
1152
|
+
};
|
|
1153
|
+
}
|
|
1154
|
+
async retrieveCBLFromPool(pool, blockId1, blockId2, _block1ParityIds, _block2ParityIds) {
|
|
1155
|
+
(0, brightchain_lib_1.validatePoolId)(pool);
|
|
1156
|
+
const b1Hex = this.keyToHex(blockId1);
|
|
1157
|
+
const b2Hex = this.keyToHex(blockId2);
|
|
1158
|
+
const block1Data = await this.getFromPool(pool, b1Hex);
|
|
1159
|
+
const block2Data = await this.getFromPool(pool, b2Hex);
|
|
1160
|
+
const reconstructedPadded = (0, brightchain_lib_1.xorArrays)(block1Data, block2Data);
|
|
1161
|
+
return (0, brightchain_lib_1.unpadCblData)(reconstructedPadded);
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
exports.CloudBlockStoreBase = CloudBlockStoreBase;
|
|
1165
|
+
//# sourceMappingURL=cloudBlockStoreBase.js.map
|