@brightchain/brightchain-lib 0.21.0 → 0.22.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/README.md +677 -0
- package/package.json +2 -2
- package/src/lib/blocks/index.d.ts +1 -0
- package/src/lib/blocks/index.d.ts.map +1 -1
- package/src/lib/blocks/index.js +1 -0
- package/src/lib/blocks/index.js.map +1 -1
- package/src/lib/blocks/tcbl/index.d.ts +7 -0
- package/src/lib/blocks/tcbl/index.d.ts.map +1 -0
- package/src/lib/blocks/tcbl/index.js +10 -0
- package/src/lib/blocks/tcbl/index.js.map +1 -0
- package/src/lib/blocks/tcbl/manifestSerializer.d.ts +79 -0
- package/src/lib/blocks/tcbl/manifestSerializer.d.ts.map +1 -0
- package/src/lib/blocks/tcbl/manifestSerializer.js +258 -0
- package/src/lib/blocks/tcbl/manifestSerializer.js.map +1 -0
- package/src/lib/blocks/tcbl/tcbl.d.ts +190 -0
- package/src/lib/blocks/tcbl/tcbl.d.ts.map +1 -0
- package/src/lib/blocks/tcbl/tcbl.js +263 -0
- package/src/lib/blocks/tcbl/tcbl.js.map +1 -0
- package/src/lib/blocks/tcbl/tcblAttachmentUtils.d.ts +49 -0
- package/src/lib/blocks/tcbl/tcblAttachmentUtils.d.ts.map +1 -0
- package/src/lib/blocks/tcbl/tcblAttachmentUtils.js +126 -0
- package/src/lib/blocks/tcbl/tcblAttachmentUtils.js.map +1 -0
- package/src/lib/blocks/tcbl/tcblBuilder.d.ts +89 -0
- package/src/lib/blocks/tcbl/tcblBuilder.d.ts.map +1 -0
- package/src/lib/blocks/tcbl/tcblBuilder.js +180 -0
- package/src/lib/blocks/tcbl/tcblBuilder.js.map +1 -0
- package/src/lib/blocks/tcbl/tcblReader.d.ts +126 -0
- package/src/lib/blocks/tcbl/tcblReader.d.ts.map +1 -0
- package/src/lib/blocks/tcbl/tcblReader.js +224 -0
- package/src/lib/blocks/tcbl/tcblReader.js.map +1 -0
- package/src/lib/blocks/tcbl/tcblValidator.d.ts +56 -0
- package/src/lib/blocks/tcbl/tcblValidator.d.ts.map +1 -0
- package/src/lib/blocks/tcbl/tcblValidator.js +100 -0
- package/src/lib/blocks/tcbl/tcblValidator.js.map +1 -0
- package/src/lib/constants.d.ts +5 -1
- package/src/lib/constants.d.ts.map +1 -1
- package/src/lib/constants.js +4 -0
- package/src/lib/constants.js.map +1 -1
- package/src/lib/ecies-config.js +1 -1
- package/src/lib/ecies-config.js.map +1 -1
- package/src/lib/enumeration-translations/blockType.d.ts.map +1 -1
- package/src/lib/enumeration-translations/blockType.js +16 -0
- package/src/lib/enumeration-translations/blockType.js.map +1 -1
- package/src/lib/enumerations/blockType.d.ts +12 -0
- package/src/lib/enumerations/blockType.d.ts.map +1 -1
- package/src/lib/enumerations/blockType.js +14 -0
- package/src/lib/enumerations/blockType.js.map +1 -1
- package/src/lib/enumerations/brightChainStrings.d.ts +12 -0
- package/src/lib/enumerations/brightChainStrings.d.ts.map +1 -1
- package/src/lib/enumerations/brightChainStrings.js +13 -0
- package/src/lib/enumerations/brightChainStrings.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 +2 -0
- package/src/lib/enumerations/index.js.map +1 -1
- package/src/lib/enumerations/tcblErrorType.d.ts +34 -0
- package/src/lib/enumerations/tcblErrorType.d.ts.map +1 -0
- package/src/lib/enumerations/tcblErrorType.js +38 -0
- package/src/lib/enumerations/tcblErrorType.js.map +1 -0
- package/src/lib/errors/index.d.ts +4 -0
- package/src/lib/errors/index.d.ts.map +1 -1
- package/src/lib/errors/index.js +7 -0
- package/src/lib/errors/index.js.map +1 -1
- package/src/lib/errors/tcblError.d.ts +30 -0
- package/src/lib/errors/tcblError.d.ts.map +1 -0
- package/src/lib/errors/tcblError.js +53 -0
- package/src/lib/errors/tcblError.js.map +1 -0
- package/src/lib/errors/typeGuards.d.ts +19 -0
- package/src/lib/errors/typeGuards.d.ts.map +1 -1
- package/src/lib/errors/typeGuards.js +22 -0
- package/src/lib/errors/typeGuards.js.map +1 -1
- package/src/lib/i18n/strings/englishUs.d.ts.map +1 -1
- package/src/lib/i18n/strings/englishUs.js +13 -0
- package/src/lib/i18n/strings/englishUs.js.map +1 -1
- package/src/lib/i18n/strings/french.d.ts.map +1 -1
- package/src/lib/i18n/strings/french.js +13 -0
- package/src/lib/i18n/strings/french.js.map +1 -1
- package/src/lib/i18n/strings/german.d.ts.map +1 -1
- package/src/lib/i18n/strings/german.js +13 -0
- package/src/lib/i18n/strings/german.js.map +1 -1
- package/src/lib/i18n/strings/japanese.d.ts.map +1 -1
- package/src/lib/i18n/strings/japanese.js +13 -0
- package/src/lib/i18n/strings/japanese.js.map +1 -1
- package/src/lib/i18n/strings/mandarin.d.ts.map +1 -1
- package/src/lib/i18n/strings/mandarin.js +13 -0
- package/src/lib/i18n/strings/mandarin.js.map +1 -1
- package/src/lib/i18n/strings/spanish.d.ts.map +1 -1
- package/src/lib/i18n/strings/spanish.js +13 -0
- package/src/lib/i18n/strings/spanish.js.map +1 -1
- package/src/lib/i18n/strings/ukrainian.d.ts.map +1 -1
- package/src/lib/i18n/strings/ukrainian.js +13 -0
- package/src/lib/i18n/strings/ukrainian.js.map +1 -1
- package/src/lib/interfaces/index.d.ts +1 -0
- package/src/lib/interfaces/index.d.ts.map +1 -1
- package/src/lib/interfaces/proposal.d.ts +22 -2
- package/src/lib/interfaces/proposal.d.ts.map +1 -1
- package/src/lib/interfaces/tcbl/index.d.ts +5 -0
- package/src/lib/interfaces/tcbl/index.d.ts.map +1 -0
- package/src/lib/interfaces/tcbl/index.js +3 -0
- package/src/lib/interfaces/tcbl/index.js.map +1 -0
- package/src/lib/interfaces/tcbl/tcblArchiveOptions.d.ts +21 -0
- package/src/lib/interfaces/tcbl/tcblArchiveOptions.d.ts.map +1 -0
- package/src/lib/interfaces/tcbl/tcblArchiveOptions.js +12 -0
- package/src/lib/interfaces/tcbl/tcblArchiveOptions.js.map +1 -0
- package/src/lib/interfaces/tcbl/tcblEntryDescriptor.d.ts +25 -0
- package/src/lib/interfaces/tcbl/tcblEntryDescriptor.d.ts.map +1 -0
- package/src/lib/interfaces/tcbl/tcblEntryDescriptor.js +10 -0
- package/src/lib/interfaces/tcbl/tcblEntryDescriptor.js.map +1 -0
- package/src/lib/interfaces/tcbl/tcblEntryInput.d.ts +21 -0
- package/src/lib/interfaces/tcbl/tcblEntryInput.d.ts.map +1 -0
- package/src/lib/interfaces/tcbl/tcblEntryInput.js +10 -0
- package/src/lib/interfaces/tcbl/tcblEntryInput.js.map +1 -0
- package/src/lib/interfaces/tcbl/tcblManifest.d.ts +28 -0
- package/src/lib/interfaces/tcbl/tcblManifest.d.ts.map +1 -0
- package/src/lib/interfaces/tcbl/tcblManifest.js +11 -0
- package/src/lib/interfaces/tcbl/tcblManifest.js.map +1 -0
- package/src/lib/services/blockCapacity.service.d.ts.map +1 -1
- package/src/lib/services/blockCapacity.service.js +3 -1
- package/src/lib/services/blockCapacity.service.js.map +1 -1
- package/src/lib/services/blockFormatService.d.ts +13 -0
- package/src/lib/services/blockFormatService.d.ts.map +1 -1
- package/src/lib/services/blockFormatService.js +24 -0
- package/src/lib/services/blockFormatService.js.map +1 -1
- package/src/lib/services/index.d.ts +1 -0
- package/src/lib/services/index.d.ts.map +1 -1
- package/src/lib/services/index.js +1 -0
- package/src/lib/services/index.js.map +1 -1
- package/src/lib/services/quorumStateMachine.d.ts.map +1 -1
- package/src/lib/services/quorumStateMachine.js +7 -2
- package/src/lib/services/quorumStateMachine.js.map +1 -1
- package/src/lib/services/sealing.service.d.ts.map +1 -1
- package/src/lib/services/sealing.service.js +19 -3
- package/src/lib/services/sealing.service.js.map +1 -1
- package/src/lib/stores/memoryCblStore.d.ts.map +1 -1
- package/src/lib/stores/memoryCblStore.js +14 -3
- package/src/lib/stores/memoryCblStore.js.map +1 -1
- package/src/lib/stores/pooledMemoryBlockStore.d.ts.map +1 -1
- package/src/lib/stores/pooledMemoryBlockStore.js +2 -1
- package/src/lib/stores/pooledMemoryBlockStore.js.map +1 -1
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview TCBL Archive Builder.
|
|
4
|
+
*
|
|
5
|
+
* Constructs a TCBL (Tarball CBL) archive from a set of input entries.
|
|
6
|
+
* Each entry's data is stored as a raw block in the block store, and a
|
|
7
|
+
* manifest is built from the entry metadata. The final TCBL is assembled
|
|
8
|
+
* as a CBL with a `StructuredBlockType.TarballCBL` header.
|
|
9
|
+
*
|
|
10
|
+
* Optional bzip2 compression can be applied to the entire payload.
|
|
11
|
+
*
|
|
12
|
+
* @typeParam TID - Platform ID type for frontend/backend DTO compatibility
|
|
13
|
+
*
|
|
14
|
+
* @see Requirement 4 (TCBL Construction)
|
|
15
|
+
* @see Requirement 7 (Whole-Archive Compression)
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.TcblBuilder = void 0;
|
|
19
|
+
const ecies_lib_1 = require("@digitaldefiance/ecies-lib");
|
|
20
|
+
const constants_1 = require("../../constants");
|
|
21
|
+
const blockEncryptionType_1 = require("../../enumerations/blockEncryptionType");
|
|
22
|
+
const blockSize_1 = require("../../enumerations/blockSize");
|
|
23
|
+
const globalServiceProvider_1 = require("../../services/globalServiceProvider");
|
|
24
|
+
const checksum_1 = require("../../types/checksum");
|
|
25
|
+
const rawData_1 = require("../rawData");
|
|
26
|
+
const manifestSerializer_1 = require("./manifestSerializer");
|
|
27
|
+
const tcbl_1 = require("./tcbl");
|
|
28
|
+
const tcblValidator_1 = require("./tcblValidator");
|
|
29
|
+
/**
|
|
30
|
+
* Builder for constructing TCBL (Tarball CBL) archives.
|
|
31
|
+
*
|
|
32
|
+
* Usage:
|
|
33
|
+
* ```typescript
|
|
34
|
+
* const builder = new TcblBuilder(creator, blockSize, blockStore);
|
|
35
|
+
* await builder.addEntry({ fileName: 'file.txt', mimeType: 'text/plain', data });
|
|
36
|
+
* const tcbl = await builder.build();
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* @typeParam TID - Platform ID type (defaults to `Uint8Array`)
|
|
40
|
+
*
|
|
41
|
+
* @see Requirement 4
|
|
42
|
+
*/
|
|
43
|
+
class TcblBuilder {
|
|
44
|
+
/**
|
|
45
|
+
* Create a new TCBL builder.
|
|
46
|
+
*
|
|
47
|
+
* @param creator - The member creating the archive
|
|
48
|
+
* @param blockSize - Block size for storing entry data
|
|
49
|
+
* @param blockStore - Block store for persisting blocks
|
|
50
|
+
* @param services - Optional CBL services for dependency injection
|
|
51
|
+
* @param options - Optional archive options (compression)
|
|
52
|
+
*
|
|
53
|
+
* @see Requirement 4.8, 4.9
|
|
54
|
+
*/
|
|
55
|
+
constructor(creator, blockSize, blockStore, services, options) {
|
|
56
|
+
/** Collected entry descriptors (populated by addEntry). */
|
|
57
|
+
this.entryDescriptors = [];
|
|
58
|
+
this.creator = creator;
|
|
59
|
+
this.blockSize = blockSize;
|
|
60
|
+
this.blockStore = blockStore;
|
|
61
|
+
this.services = services;
|
|
62
|
+
this.compress = options?.compress ?? false;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Add an entry to the archive.
|
|
66
|
+
*
|
|
67
|
+
* Validates the input, stores the entry data as a raw block in the
|
|
68
|
+
* block store, and records the entry descriptor for the manifest.
|
|
69
|
+
*
|
|
70
|
+
* @param input - The entry input (fileName, mimeType, data)
|
|
71
|
+
*
|
|
72
|
+
* @throws {TcblError} if validation fails (file name too long,
|
|
73
|
+
* path traversal, MIME type too long)
|
|
74
|
+
*
|
|
75
|
+
* @see Requirement 4.1, 4.2
|
|
76
|
+
*/
|
|
77
|
+
async addEntry(input) {
|
|
78
|
+
// Validate the entry input
|
|
79
|
+
tcblValidator_1.TcblValidator.validateFileName(input.fileName);
|
|
80
|
+
tcblValidator_1.TcblValidator.validateMimeType(input.mimeType);
|
|
81
|
+
// Store entry data as a raw block
|
|
82
|
+
const checksumService = this.services?.checksumService ??
|
|
83
|
+
(0, globalServiceProvider_1.getGlobalServiceProvider)().checksumService;
|
|
84
|
+
const checksum = checksumService.calculateChecksum(input.data);
|
|
85
|
+
const rawBlock = new rawData_1.RawDataBlock(this.blockSize, input.data, undefined, checksum);
|
|
86
|
+
await this.blockStore.setData(rawBlock);
|
|
87
|
+
// Record the entry descriptor
|
|
88
|
+
this.entryDescriptors.push({
|
|
89
|
+
fileName: input.fileName,
|
|
90
|
+
mimeType: input.mimeType,
|
|
91
|
+
originalDataLength: input.data.length,
|
|
92
|
+
cblAddress: checksum,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Build the TCBL archive.
|
|
97
|
+
*
|
|
98
|
+
* Constructs the manifest from collected entries, serializes it,
|
|
99
|
+
* optionally compresses the payload, creates a CBL header with
|
|
100
|
+
* `StructuredBlockType.TarballCBL`, and returns the final TCBL block.
|
|
101
|
+
*
|
|
102
|
+
* @returns The constructed TCBL block
|
|
103
|
+
*
|
|
104
|
+
* @see Requirement 4.3, 4.4, 4.5, 4.7, 4.10, 7.1, 7.3
|
|
105
|
+
*/
|
|
106
|
+
async build() {
|
|
107
|
+
const checksumService = this.services?.checksumService ??
|
|
108
|
+
(0, globalServiceProvider_1.getGlobalServiceProvider)().checksumService;
|
|
109
|
+
const cblService = this.services?.cblService ?? (0, globalServiceProvider_1.getGlobalServiceProvider)().cblService;
|
|
110
|
+
// Build the manifest
|
|
111
|
+
const manifest = {
|
|
112
|
+
version: 1,
|
|
113
|
+
entryCount: this.entryDescriptors.length,
|
|
114
|
+
entries: [...this.entryDescriptors],
|
|
115
|
+
checksum: checksum_1.Checksum.fromUint8Array(new Uint8Array(ecies_lib_1.CHECKSUM.SHA3_BUFFER_LENGTH)),
|
|
116
|
+
};
|
|
117
|
+
// Serialize the manifest
|
|
118
|
+
const serializedManifest = manifestSerializer_1.TcblManifestSerializer.serialize(manifest);
|
|
119
|
+
// Assemble the TCBL payload: [compressionFlag(1)][manifestData]
|
|
120
|
+
let manifestData;
|
|
121
|
+
if (this.compress) {
|
|
122
|
+
// Dynamic import to avoid ESM/CJS issues at module load time
|
|
123
|
+
const BZip2Module = await Promise.resolve().then(() => require('bzip2-wasm'));
|
|
124
|
+
const BZip2 = BZip2Module.default;
|
|
125
|
+
const bzip2 = new BZip2();
|
|
126
|
+
await bzip2.init();
|
|
127
|
+
const compressed = bzip2.compress(serializedManifest);
|
|
128
|
+
// Store uncompressed length as uint32 BE so decompressor knows buffer size
|
|
129
|
+
const withLength = new Uint8Array(4 + compressed.length);
|
|
130
|
+
const view = new DataView(withLength.buffer, withLength.byteOffset, withLength.byteLength);
|
|
131
|
+
view.setUint32(0, serializedManifest.length, false);
|
|
132
|
+
withLength.set(compressed, 4);
|
|
133
|
+
manifestData = withLength;
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
manifestData = serializedManifest;
|
|
137
|
+
}
|
|
138
|
+
// Full payload: [compressionFlag(1 byte)][manifestData]
|
|
139
|
+
const payload = new Uint8Array(1 + manifestData.length);
|
|
140
|
+
payload[0] = this.compress ? 0x01 : 0x00;
|
|
141
|
+
payload.set(manifestData, 1);
|
|
142
|
+
// Store the payload as a raw block so we have an address for it
|
|
143
|
+
const payloadChecksum = checksumService.calculateChecksum(payload);
|
|
144
|
+
const payloadBlock = new rawData_1.RawDataBlock(this.blockSize, payload, undefined, payloadChecksum);
|
|
145
|
+
await this.blockStore.setData(payloadBlock);
|
|
146
|
+
// Build the address list: entry data checksums + payload checksum
|
|
147
|
+
const allAddresses = [
|
|
148
|
+
...this.entryDescriptors.map((e) => e.cblAddress),
|
|
149
|
+
payloadChecksum,
|
|
150
|
+
];
|
|
151
|
+
const addressBytes = ecies_lib_1.CHECKSUM.SHA3_BUFFER_LENGTH;
|
|
152
|
+
const addressList = new Uint8Array(allAddresses.length * addressBytes);
|
|
153
|
+
for (let i = 0; i < allAddresses.length; i++) {
|
|
154
|
+
addressList.set(allAddresses[i].toUint8Array(), i * addressBytes);
|
|
155
|
+
}
|
|
156
|
+
// Create CBL header via cblService.makeCblHeader
|
|
157
|
+
// Use Small block size to ensure enough capacity for addresses
|
|
158
|
+
const cblBlockSize = blockSize_1.BlockSize.Small;
|
|
159
|
+
const { headerData } = cblService.makeCblHeader(this.creator, new Date(), allAddresses.length, payload.length, addressList, cblBlockSize, blockEncryptionType_1.BlockEncryptionType.None, undefined, constants_1.TUPLE.SIZE);
|
|
160
|
+
// Patch the structured block type byte from CBL to TarballCBL.
|
|
161
|
+
// The CRC8 is computed over baseHeader + extendedHeaderData (not the
|
|
162
|
+
// structured prefix), and the signature is computed over
|
|
163
|
+
// baseHeader + extendedHeaderData + blockSize + addressList.
|
|
164
|
+
// Neither includes byte[1], so patching is safe.
|
|
165
|
+
const patchedHeader = new Uint8Array(headerData);
|
|
166
|
+
patchedHeader[1] = constants_1.StructuredBlockType.TarballCBL;
|
|
167
|
+
// Assemble the full block data: header + addresses, padded to block size
|
|
168
|
+
const blockSizeBytes = cblBlockSize;
|
|
169
|
+
const data = new Uint8Array(blockSizeBytes);
|
|
170
|
+
data.set(patchedHeader, 0);
|
|
171
|
+
data.set(addressList, patchedHeader.length);
|
|
172
|
+
// Create the TarballConstituentBlockListBlock
|
|
173
|
+
const tcblBlock = new tcbl_1.TarballConstituentBlockListBlock(data, this.creator, cblBlockSize, this.services);
|
|
174
|
+
// Set the payload data so the manifest can be accessed
|
|
175
|
+
tcblBlock.setPayloadData(payload);
|
|
176
|
+
return tcblBlock;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
exports.TcblBuilder = TcblBuilder;
|
|
180
|
+
//# sourceMappingURL=tcblBuilder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tcblBuilder.js","sourceRoot":"","sources":["../../../../../../brightchain-lib/src/lib/blocks/tcbl/tcblBuilder.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAEH,0DAA+E;AAC/E,+CAA6D;AAC7D,gFAA6E;AAC7E,4DAAyD;AAOzD,gFAAgF;AAChF,mDAAgD;AAChD,wCAA0C;AAC1C,6DAA8D;AAC9D,iCAA0D;AAC1D,mDAAgD;AAEhD;;;;;;;;;;;;;GAaG;AACH,MAAa,WAAW;IAmBtB;;;;;;;;;;OAUG;IACH,YACE,OAAoB,EACpB,SAAoB,EACpB,UAAuB,EACvB,QAA4B,EAC5B,OAA6B;QAnB/B,2DAA2D;QAC1C,qBAAgB,GAA2B,EAAE,CAAC;QAoB7D,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,KAAK,CAAC;IAC7C,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,QAAQ,CAAC,KAAsB;QACnC,2BAA2B;QAC3B,6BAAa,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC/C,6BAAa,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAE/C,kCAAkC;QAClC,MAAM,eAAe,GACnB,IAAI,CAAC,QAAQ,EAAE,eAAe;YAC9B,IAAA,gDAAwB,GAAO,CAAC,eAAe,CAAC;QAClD,MAAM,QAAQ,GAAG,eAAe,CAAC,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/D,MAAM,QAAQ,GAAG,IAAI,sBAAY,CAC/B,IAAI,CAAC,SAAS,EACd,KAAK,CAAC,IAAI,EACV,SAAS,EACT,QAAQ,CACT,CAAC;QACF,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAExC,8BAA8B;QAC9B,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC;YACzB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,kBAAkB,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM;YACrC,UAAU,EAAE,QAAQ;SACrB,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,KAAK;QACT,MAAM,eAAe,GACnB,IAAI,CAAC,QAAQ,EAAE,eAAe;YAC9B,IAAA,gDAAwB,GAAO,CAAC,eAAe,CAAC;QAClD,MAAM,UAAU,GACd,IAAI,CAAC,QAAQ,EAAE,UAAU,IAAI,IAAA,gDAAwB,GAAO,CAAC,UAAU,CAAC;QAE1E,qBAAqB;QACrB,MAAM,QAAQ,GAAkB;YAC9B,OAAO,EAAE,CAAC;YACV,UAAU,EAAE,IAAI,CAAC,gBAAgB,CAAC,MAAM;YACxC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC;YACnC,QAAQ,EAAE,mBAAQ,CAAC,cAAc,CAC/B,IAAI,UAAU,CAAC,oBAAQ,CAAC,kBAAkB,CAAC,CAC5C;SACF,CAAC;QAEF,yBAAyB;QACzB,MAAM,kBAAkB,GAAG,2CAAsB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAEtE,gEAAgE;QAChE,IAAI,YAAwB,CAAC;QAC7B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,6DAA6D;YAC7D,MAAM,WAAW,GAAG,2CAAa,YAAY,EAAC,CAAC;YAC/C,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC;YAClC,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;YAC1B,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;YACtD,2EAA2E;YAC3E,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;YACzD,MAAM,IAAI,GAAG,IAAI,QAAQ,CACvB,UAAU,CAAC,MAAM,EACjB,UAAU,CAAC,UAAU,EACrB,UAAU,CAAC,UAAU,CACtB,CAAC;YACF,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YACpD,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;YAC9B,YAAY,GAAG,UAAU,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,YAAY,GAAG,kBAAkB,CAAC;QACpC,CAAC;QAED,wDAAwD;QACxD,MAAM,OAAO,GAAG,IAAI,UAAU,CAAC,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;QACxD,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QAE7B,gEAAgE;QAChE,MAAM,eAAe,GAAG,eAAe,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACnE,MAAM,YAAY,GAAG,IAAI,sBAAY,CACnC,IAAI,CAAC,SAAS,EACd,OAAO,EACP,SAAS,EACT,eAAe,CAChB,CAAC;QACF,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAE5C,kEAAkE;QAClE,MAAM,YAAY,GAAe;YAC/B,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;YACjD,eAAe;SAChB,CAAC;QACF,MAAM,YAAY,GAAG,oBAAQ,CAAC,kBAAkB,CAAC;QACjD,MAAM,WAAW,GAAG,IAAI,UAAU,CAAC,YAAY,CAAC,MAAM,GAAG,YAAY,CAAC,CAAC;QACvE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC;QACpE,CAAC;QAED,iDAAiD;QACjD,+DAA+D;QAC/D,MAAM,YAAY,GAAG,qBAAS,CAAC,KAAK,CAAC;QACrC,MAAM,EAAE,UAAU,EAAE,GAAG,UAAU,CAAC,aAAa,CAC7C,IAAI,CAAC,OAAO,EACZ,IAAI,IAAI,EAAE,EACV,YAAY,CAAC,MAAM,EACnB,OAAO,CAAC,MAAM,EACd,WAAW,EACX,YAAY,EACZ,yCAAmB,CAAC,IAAI,EACxB,SAAS,EACT,iBAAK,CAAC,IAAI,CACX,CAAC;QAEF,+DAA+D;QAC/D,qEAAqE;QACrE,yDAAyD;QACzD,6DAA6D;QAC7D,iDAAiD;QACjD,MAAM,aAAa,GAAG,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC;QACjD,aAAa,CAAC,CAAC,CAAC,GAAG,+BAAmB,CAAC,UAAU,CAAC;QAElD,yEAAyE;QACzE,MAAM,cAAc,GAAG,YAAsB,CAAC;QAC9C,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,cAAc,CAAC,CAAC;QAC5C,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;QAC3B,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;QAE5C,8CAA8C;QAC9C,MAAM,SAAS,GAAG,IAAI,uCAAgC,CACpD,IAAI,EACJ,IAAI,CAAC,OAAO,EACZ,YAAY,EACZ,IAAI,CAAC,QAAQ,CACd,CAAC;QAEF,uDAAuD;QACvD,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAElC,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;AA9MD,kCA8MC"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview TCBL Archive Reader.
|
|
3
|
+
*
|
|
4
|
+
* Reads and extracts entries from a TCBL (Tarball CBL) archive.
|
|
5
|
+
* The reader receives an already-constructed {@link TarballConstituentBlockListBlock}
|
|
6
|
+
* and a block store. Decryption of any `EncryptedBlock` wrapper is the
|
|
7
|
+
* caller's responsibility.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const reader = new TcblReader(tcblBlock, blockStore);
|
|
12
|
+
* await reader.open();
|
|
13
|
+
* const entries = reader.listEntries();
|
|
14
|
+
* const data = await reader.getEntryByName('file.txt');
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @typeParam TID - Platform ID type for frontend/backend DTO compatibility
|
|
18
|
+
*
|
|
19
|
+
* @see Requirement 5 (TCBL Reading and Extraction)
|
|
20
|
+
*/
|
|
21
|
+
import { PlatformID } from '@digitaldefiance/ecies-lib';
|
|
22
|
+
import { IBlockStore } from '../../interfaces/storage/blockStore';
|
|
23
|
+
import { ITcblEntryDescriptor } from '../../interfaces/tcbl/tcblEntryDescriptor';
|
|
24
|
+
import { TarballConstituentBlockListBlock } from './tcbl';
|
|
25
|
+
/**
|
|
26
|
+
* Reader for TCBL (Tarball CBL) archives.
|
|
27
|
+
*
|
|
28
|
+
* Provides methods to enumerate manifest entries and extract individual
|
|
29
|
+
* entry data from the block store. The {@link open} method must be called
|
|
30
|
+
* before any other operations.
|
|
31
|
+
*
|
|
32
|
+
* @typeParam TID - Platform ID type (defaults to `Uint8Array`)
|
|
33
|
+
*
|
|
34
|
+
* @see Requirement 5
|
|
35
|
+
*/
|
|
36
|
+
export declare class TcblReader<TID extends PlatformID = Uint8Array> {
|
|
37
|
+
/** The TCBL block being read. */
|
|
38
|
+
private readonly tcblBlock;
|
|
39
|
+
/** Block store for retrieving entry data. */
|
|
40
|
+
private readonly blockStore;
|
|
41
|
+
/** Whether {@link open} has been called successfully. */
|
|
42
|
+
private _isOpen;
|
|
43
|
+
/** Cached manifest entries after open(). */
|
|
44
|
+
private _entries;
|
|
45
|
+
/**
|
|
46
|
+
* Create a new TCBL reader.
|
|
47
|
+
*
|
|
48
|
+
* @param tcblBlock - The TCBL block to read (must be already decrypted)
|
|
49
|
+
* @param blockStore - Block store for retrieving entry data blocks
|
|
50
|
+
*
|
|
51
|
+
* @see Requirement 5.7 — decryption is the caller's responsibility
|
|
52
|
+
*/
|
|
53
|
+
constructor(tcblBlock: TarballConstituentBlockListBlock<TID>, blockStore: IBlockStore);
|
|
54
|
+
/**
|
|
55
|
+
* Open the archive for reading.
|
|
56
|
+
*
|
|
57
|
+
* Retrieves the payload block from the block store (last address in
|
|
58
|
+
* the CBL's address list), handles decompression if the payload is
|
|
59
|
+
* bzip2-compressed, sets the payload data on the TCBL block, and
|
|
60
|
+
* validates the manifest checksum.
|
|
61
|
+
*
|
|
62
|
+
* Must be called before {@link listEntries}, {@link getEntryByIndex},
|
|
63
|
+
* or {@link getEntryByName}.
|
|
64
|
+
*
|
|
65
|
+
* @throws {TcblError} with {@link TcblErrorType.DecompressionFailed}
|
|
66
|
+
* if bzip2 decompression fails
|
|
67
|
+
* @throws {TcblError} with {@link TcblErrorType.ManifestChecksumMismatch}
|
|
68
|
+
* if the manifest checksum does not match
|
|
69
|
+
* @throws {TcblError} with {@link TcblErrorType.ManifestCorrupted}
|
|
70
|
+
* if the manifest is structurally invalid
|
|
71
|
+
*
|
|
72
|
+
* @see Requirement 5.1, 5.2, 5.5
|
|
73
|
+
*/
|
|
74
|
+
open(): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Ensure the archive has been opened.
|
|
77
|
+
*
|
|
78
|
+
* @throws {TcblError} with {@link TcblErrorType.InvalidHeader} if
|
|
79
|
+
* {@link open} has not been called
|
|
80
|
+
*/
|
|
81
|
+
private ensureOpen;
|
|
82
|
+
/**
|
|
83
|
+
* List all entry descriptors from the manifest without extracting data.
|
|
84
|
+
*
|
|
85
|
+
* @returns Array of entry descriptors
|
|
86
|
+
* @throws {TcblError} if the archive has not been opened
|
|
87
|
+
*
|
|
88
|
+
* @see Requirement 5.3
|
|
89
|
+
*/
|
|
90
|
+
listEntries(): ITcblEntryDescriptor[];
|
|
91
|
+
/**
|
|
92
|
+
* Retrieve entry data by index.
|
|
93
|
+
*
|
|
94
|
+
* @param index - Zero-based index into the manifest entries
|
|
95
|
+
* @returns The entry's original data (trimmed to originalDataLength)
|
|
96
|
+
*
|
|
97
|
+
* @throws {TcblError} with {@link TcblErrorType.EntryNotFound} if
|
|
98
|
+
* the index is out of range
|
|
99
|
+
*
|
|
100
|
+
* @see Requirement 5.4, 5.6
|
|
101
|
+
*/
|
|
102
|
+
getEntryByIndex(index: number): Promise<Uint8Array>;
|
|
103
|
+
/**
|
|
104
|
+
* Retrieve entry data by file name.
|
|
105
|
+
*
|
|
106
|
+
* @param fileName - The file name to search for in the manifest
|
|
107
|
+
* @returns The entry's original data (trimmed to originalDataLength)
|
|
108
|
+
*
|
|
109
|
+
* @throws {TcblError} with {@link TcblErrorType.EntryNotFound} if
|
|
110
|
+
* no entry with the given file name exists
|
|
111
|
+
*
|
|
112
|
+
* @see Requirement 5.4, 5.6
|
|
113
|
+
*/
|
|
114
|
+
getEntryByName(fileName: string): Promise<Uint8Array>;
|
|
115
|
+
/**
|
|
116
|
+
* Retrieve the raw data for a manifest entry from the block store.
|
|
117
|
+
*
|
|
118
|
+
* The block store returns a {@link RawDataBlock} padded to block size,
|
|
119
|
+
* so we trim to `originalDataLength` to get the actual data.
|
|
120
|
+
*
|
|
121
|
+
* @param entry - The entry descriptor from the manifest
|
|
122
|
+
* @returns The entry's original data bytes
|
|
123
|
+
*/
|
|
124
|
+
private retrieveEntryData;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=tcblReader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tcblReader.d.ts","sourceRoot":"","sources":["../../../../../../brightchain-lib/src/lib/blocks/tcbl/tcblReader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAGxD,OAAO,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,gCAAgC,EAAE,MAAM,QAAQ,CAAC;AAE1D;;;;;;;;;;GAUG;AACH,qBAAa,UAAU,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU;IACzD,iCAAiC;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwC;IAElE,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAc;IAEzC,yDAAyD;IACzD,OAAO,CAAC,OAAO,CAAS;IAExB,4CAA4C;IAC5C,OAAO,CAAC,QAAQ,CAA8B;IAE9C;;;;;;;OAOG;gBAED,SAAS,EAAE,gCAAgC,CAAC,GAAG,CAAC,EAChD,UAAU,EAAE,WAAW;IAMzB;;;;;;;;;;;;;;;;;;;OAmBG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoF3B;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IASlB;;;;;;;OAOG;IACH,WAAW,IAAI,oBAAoB,EAAE;IAKrC;;;;;;;;;;OAUG;IACG,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAiBzD;;;;;;;;;;OAUG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAc3D;;;;;;;;OAQG;YACW,iBAAiB;CAMhC"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview TCBL Archive Reader.
|
|
4
|
+
*
|
|
5
|
+
* Reads and extracts entries from a TCBL (Tarball CBL) archive.
|
|
6
|
+
* The reader receives an already-constructed {@link TarballConstituentBlockListBlock}
|
|
7
|
+
* and a block store. Decryption of any `EncryptedBlock` wrapper is the
|
|
8
|
+
* caller's responsibility.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const reader = new TcblReader(tcblBlock, blockStore);
|
|
13
|
+
* await reader.open();
|
|
14
|
+
* const entries = reader.listEntries();
|
|
15
|
+
* const data = await reader.getEntryByName('file.txt');
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @typeParam TID - Platform ID type for frontend/backend DTO compatibility
|
|
19
|
+
*
|
|
20
|
+
* @see Requirement 5 (TCBL Reading and Extraction)
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.TcblReader = void 0;
|
|
24
|
+
const tcblErrorType_1 = require("../../enumerations/tcblErrorType");
|
|
25
|
+
const tcblError_1 = require("../../errors/tcblError");
|
|
26
|
+
/**
|
|
27
|
+
* Reader for TCBL (Tarball CBL) archives.
|
|
28
|
+
*
|
|
29
|
+
* Provides methods to enumerate manifest entries and extract individual
|
|
30
|
+
* entry data from the block store. The {@link open} method must be called
|
|
31
|
+
* before any other operations.
|
|
32
|
+
*
|
|
33
|
+
* @typeParam TID - Platform ID type (defaults to `Uint8Array`)
|
|
34
|
+
*
|
|
35
|
+
* @see Requirement 5
|
|
36
|
+
*/
|
|
37
|
+
class TcblReader {
|
|
38
|
+
/**
|
|
39
|
+
* Create a new TCBL reader.
|
|
40
|
+
*
|
|
41
|
+
* @param tcblBlock - The TCBL block to read (must be already decrypted)
|
|
42
|
+
* @param blockStore - Block store for retrieving entry data blocks
|
|
43
|
+
*
|
|
44
|
+
* @see Requirement 5.7 — decryption is the caller's responsibility
|
|
45
|
+
*/
|
|
46
|
+
constructor(tcblBlock, blockStore) {
|
|
47
|
+
/** Whether {@link open} has been called successfully. */
|
|
48
|
+
this._isOpen = false;
|
|
49
|
+
/** Cached manifest entries after open(). */
|
|
50
|
+
this._entries = [];
|
|
51
|
+
this.tcblBlock = tcblBlock;
|
|
52
|
+
this.blockStore = blockStore;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Open the archive for reading.
|
|
56
|
+
*
|
|
57
|
+
* Retrieves the payload block from the block store (last address in
|
|
58
|
+
* the CBL's address list), handles decompression if the payload is
|
|
59
|
+
* bzip2-compressed, sets the payload data on the TCBL block, and
|
|
60
|
+
* validates the manifest checksum.
|
|
61
|
+
*
|
|
62
|
+
* Must be called before {@link listEntries}, {@link getEntryByIndex},
|
|
63
|
+
* or {@link getEntryByName}.
|
|
64
|
+
*
|
|
65
|
+
* @throws {TcblError} with {@link TcblErrorType.DecompressionFailed}
|
|
66
|
+
* if bzip2 decompression fails
|
|
67
|
+
* @throws {TcblError} with {@link TcblErrorType.ManifestChecksumMismatch}
|
|
68
|
+
* if the manifest checksum does not match
|
|
69
|
+
* @throws {TcblError} with {@link TcblErrorType.ManifestCorrupted}
|
|
70
|
+
* if the manifest is structurally invalid
|
|
71
|
+
*
|
|
72
|
+
* @see Requirement 5.1, 5.2, 5.5
|
|
73
|
+
*/
|
|
74
|
+
async open() {
|
|
75
|
+
// Retrieve the payload block — it's the last address in the CBL
|
|
76
|
+
const addresses = this.tcblBlock.addresses;
|
|
77
|
+
const payloadAddress = addresses[addresses.length - 1];
|
|
78
|
+
const payloadBlock = await this.blockStore.getData(payloadAddress);
|
|
79
|
+
const rawPayload = payloadBlock.data;
|
|
80
|
+
// Check the compression flag (byte 0)
|
|
81
|
+
const compressionFlag = rawPayload[0];
|
|
82
|
+
let decompressedPayload;
|
|
83
|
+
if (compressionFlag === 0x01) {
|
|
84
|
+
// Compressed: [0x01][uncompressedLength(4 bytes BE)][bzip2 data]
|
|
85
|
+
try {
|
|
86
|
+
const view = new DataView(rawPayload.buffer, rawPayload.byteOffset, rawPayload.byteLength);
|
|
87
|
+
const uncompressedLength = view.getUint32(1, false);
|
|
88
|
+
const compressedData = rawPayload.subarray(5);
|
|
89
|
+
const BZip2Module = await Promise.resolve().then(() => require('bzip2-wasm'));
|
|
90
|
+
const BZip2 = BZip2Module.default;
|
|
91
|
+
const bzip2 = new BZip2();
|
|
92
|
+
await bzip2.init();
|
|
93
|
+
const decompressedManifest = bzip2.decompress(compressedData, uncompressedLength);
|
|
94
|
+
// Build a new uncompressed payload: [0x00][decompressedManifest]
|
|
95
|
+
decompressedPayload = new Uint8Array(1 + decompressedManifest.length);
|
|
96
|
+
decompressedPayload[0] = 0x00;
|
|
97
|
+
decompressedPayload.set(decompressedManifest, 1);
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
if (e instanceof tcblError_1.TcblError)
|
|
101
|
+
throw e;
|
|
102
|
+
throw new tcblError_1.TcblError(tcblErrorType_1.TcblErrorType.DecompressionFailed, new Map([['reason', String(e)]]));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
// Uncompressed: use as-is
|
|
107
|
+
decompressedPayload = rawPayload;
|
|
108
|
+
}
|
|
109
|
+
// Set the (decompressed) payload on the TCBL block.
|
|
110
|
+
// This will parse the manifest via the block's manifest getter.
|
|
111
|
+
// The deserializer validates the manifest checksum internally,
|
|
112
|
+
// throwing ManifestCorrupted if it doesn't match.
|
|
113
|
+
try {
|
|
114
|
+
this.tcblBlock.setPayloadData(decompressedPayload);
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
if (e instanceof tcblError_1.TcblError) {
|
|
118
|
+
// Re-map ManifestCorrupted to ManifestChecksumMismatch if it's
|
|
119
|
+
// a checksum issue (the deserializer throws ManifestCorrupted
|
|
120
|
+
// for checksum failures)
|
|
121
|
+
if (e.errorType === tcblErrorType_1.TcblErrorType.ManifestCorrupted) {
|
|
122
|
+
throw new tcblError_1.TcblError(tcblErrorType_1.TcblErrorType.ManifestChecksumMismatch);
|
|
123
|
+
}
|
|
124
|
+
throw e;
|
|
125
|
+
}
|
|
126
|
+
throw e;
|
|
127
|
+
}
|
|
128
|
+
// Access the manifest to trigger deserialization and checksum validation.
|
|
129
|
+
// The manifest getter calls TcblManifestSerializer.deserialize() which
|
|
130
|
+
// validates the checksum internally.
|
|
131
|
+
try {
|
|
132
|
+
this._entries = [...this.tcblBlock.manifest.entries];
|
|
133
|
+
}
|
|
134
|
+
catch (e) {
|
|
135
|
+
if (e instanceof tcblError_1.TcblError) {
|
|
136
|
+
if (e.errorType === tcblErrorType_1.TcblErrorType.ManifestCorrupted) {
|
|
137
|
+
throw new tcblError_1.TcblError(tcblErrorType_1.TcblErrorType.ManifestChecksumMismatch);
|
|
138
|
+
}
|
|
139
|
+
throw e;
|
|
140
|
+
}
|
|
141
|
+
throw e;
|
|
142
|
+
}
|
|
143
|
+
this._isOpen = true;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Ensure the archive has been opened.
|
|
147
|
+
*
|
|
148
|
+
* @throws {TcblError} with {@link TcblErrorType.InvalidHeader} if
|
|
149
|
+
* {@link open} has not been called
|
|
150
|
+
*/
|
|
151
|
+
ensureOpen() {
|
|
152
|
+
if (!this._isOpen) {
|
|
153
|
+
throw new tcblError_1.TcblError(tcblErrorType_1.TcblErrorType.InvalidHeader, new Map([['reason', 'archive not opened; call open() first']]));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* List all entry descriptors from the manifest without extracting data.
|
|
158
|
+
*
|
|
159
|
+
* @returns Array of entry descriptors
|
|
160
|
+
* @throws {TcblError} if the archive has not been opened
|
|
161
|
+
*
|
|
162
|
+
* @see Requirement 5.3
|
|
163
|
+
*/
|
|
164
|
+
listEntries() {
|
|
165
|
+
this.ensureOpen();
|
|
166
|
+
return [...this._entries];
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Retrieve entry data by index.
|
|
170
|
+
*
|
|
171
|
+
* @param index - Zero-based index into the manifest entries
|
|
172
|
+
* @returns The entry's original data (trimmed to originalDataLength)
|
|
173
|
+
*
|
|
174
|
+
* @throws {TcblError} with {@link TcblErrorType.EntryNotFound} if
|
|
175
|
+
* the index is out of range
|
|
176
|
+
*
|
|
177
|
+
* @see Requirement 5.4, 5.6
|
|
178
|
+
*/
|
|
179
|
+
async getEntryByIndex(index) {
|
|
180
|
+
this.ensureOpen();
|
|
181
|
+
if (index < 0 || index >= this._entries.length) {
|
|
182
|
+
throw new tcblError_1.TcblError(tcblErrorType_1.TcblErrorType.EntryNotFound, new Map([
|
|
183
|
+
['index', String(index)],
|
|
184
|
+
['entryCount', String(this._entries.length)],
|
|
185
|
+
]));
|
|
186
|
+
}
|
|
187
|
+
const entry = this._entries[index];
|
|
188
|
+
return this.retrieveEntryData(entry);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Retrieve entry data by file name.
|
|
192
|
+
*
|
|
193
|
+
* @param fileName - The file name to search for in the manifest
|
|
194
|
+
* @returns The entry's original data (trimmed to originalDataLength)
|
|
195
|
+
*
|
|
196
|
+
* @throws {TcblError} with {@link TcblErrorType.EntryNotFound} if
|
|
197
|
+
* no entry with the given file name exists
|
|
198
|
+
*
|
|
199
|
+
* @see Requirement 5.4, 5.6
|
|
200
|
+
*/
|
|
201
|
+
async getEntryByName(fileName) {
|
|
202
|
+
this.ensureOpen();
|
|
203
|
+
const entry = this._entries.find((e) => e.fileName === fileName);
|
|
204
|
+
if (!entry) {
|
|
205
|
+
throw new tcblError_1.TcblError(tcblErrorType_1.TcblErrorType.EntryNotFound, new Map([['fileName', fileName]]));
|
|
206
|
+
}
|
|
207
|
+
return this.retrieveEntryData(entry);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Retrieve the raw data for a manifest entry from the block store.
|
|
211
|
+
*
|
|
212
|
+
* The block store returns a {@link RawDataBlock} padded to block size,
|
|
213
|
+
* so we trim to `originalDataLength` to get the actual data.
|
|
214
|
+
*
|
|
215
|
+
* @param entry - The entry descriptor from the manifest
|
|
216
|
+
* @returns The entry's original data bytes
|
|
217
|
+
*/
|
|
218
|
+
async retrieveEntryData(entry) {
|
|
219
|
+
const rawBlock = await this.blockStore.getData(entry.cblAddress);
|
|
220
|
+
return rawBlock.data.subarray(0, entry.originalDataLength);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
exports.TcblReader = TcblReader;
|
|
224
|
+
//# sourceMappingURL=tcblReader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tcblReader.js","sourceRoot":"","sources":["../../../../../../brightchain-lib/src/lib/blocks/tcbl/tcblReader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview TCBL input validation utilities.
|
|
3
|
+
*
|
|
4
|
+
* Provides static validation methods for TCBL entry inputs including
|
|
5
|
+
* file name length/traversal checks and MIME type length checks.
|
|
6
|
+
*
|
|
7
|
+
* @see Requirement 10 (Validation and Error Handling)
|
|
8
|
+
*/
|
|
9
|
+
import { ITcblEntryInput } from '../../interfaces/tcbl/tcblEntryInput';
|
|
10
|
+
/**
|
|
11
|
+
* Static validation utilities for TCBL archive entry inputs.
|
|
12
|
+
*
|
|
13
|
+
* All methods throw {@link TcblError} with the appropriate
|
|
14
|
+
* {@link TcblErrorType} on validation failure.
|
|
15
|
+
*/
|
|
16
|
+
export declare class TcblValidator {
|
|
17
|
+
/**
|
|
18
|
+
* Validate a file name for TCBL entry use.
|
|
19
|
+
*
|
|
20
|
+
* Rejects names that:
|
|
21
|
+
* - Exceed {@link CBL.MAX_FILE_NAME_LENGTH} (255) characters
|
|
22
|
+
* - Contain path traversal sequences (`../`, `..\\`)
|
|
23
|
+
* - Start with `/` or `\\` (absolute paths)
|
|
24
|
+
*
|
|
25
|
+
* @param name - The file name to validate
|
|
26
|
+
* @throws {TcblError} with {@link TcblErrorType.FileNameTooLong} if name exceeds 255 chars
|
|
27
|
+
* @throws {TcblError} with {@link TcblErrorType.PathTraversal} if name contains traversal or absolute path
|
|
28
|
+
*
|
|
29
|
+
* @see Requirement 10.5, 10.7
|
|
30
|
+
*/
|
|
31
|
+
static validateFileName(name: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* Validate a MIME type for TCBL entry use.
|
|
34
|
+
*
|
|
35
|
+
* Rejects MIME types that exceed {@link CBL.MAX_MIME_TYPE_LENGTH} (127) characters.
|
|
36
|
+
*
|
|
37
|
+
* @param mimeType - The MIME type string to validate
|
|
38
|
+
* @throws {TcblError} with {@link TcblErrorType.MimeTypeTooLong} if mimeType exceeds 127 chars
|
|
39
|
+
*
|
|
40
|
+
* @see Requirement 10.6
|
|
41
|
+
*/
|
|
42
|
+
static validateMimeType(mimeType: string): void;
|
|
43
|
+
/**
|
|
44
|
+
* Validate all entries in an array of TCBL entry inputs.
|
|
45
|
+
*
|
|
46
|
+
* Validates each entry's file name and MIME type, throwing a
|
|
47
|
+
* {@link TcblError} on the first violation encountered.
|
|
48
|
+
*
|
|
49
|
+
* @param entries - The array of entry inputs to validate
|
|
50
|
+
* @throws {TcblError} on the first validation failure
|
|
51
|
+
*
|
|
52
|
+
* @see Requirement 10.5, 10.6, 10.7
|
|
53
|
+
*/
|
|
54
|
+
static validateEntryInputs(entries: ITcblEntryInput[]): void;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=tcblValidator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tcblValidator.d.ts","sourceRoot":"","sources":["../../../../../../brightchain-lib/src/lib/blocks/tcbl/tcblValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAEvE;;;;;GAKG;AACH,qBAAa,aAAa;IACxB;;;;;;;;;;;;;OAaG;WACW,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAmClD;;;;;;;;;OASG;WACW,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAgBtD;;;;;;;;;;OAUG;WACW,mBAAmB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,IAAI;CAMpE"}
|