@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
package/README.md
ADDED
|
@@ -0,0 +1,677 @@
|
|
|
1
|
+
# BrightChain Library
|
|
2
|
+
|
|
3
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
[](https://badge.fury.io/js/%40brightchain%2Fbrightchain-lib)
|
|
5
|
+
|
|
6
|
+
**BrightChain** is a revolutionary cryptographic ecosystem that reimagines digital governance, storage, and communication. At its core, it implements the Owner-Free File System (OFFS) with advanced cryptographic features including ECIES encryption, homomorphic voting capabilities, and brokered anonymity.
|
|
7
|
+
|
|
8
|
+
## 🌟 Key Features
|
|
9
|
+
|
|
10
|
+
### 🔐 Unified Cryptographic Architecture
|
|
11
|
+
- **ECIES Integration**: Elliptic Curve Integrated Encryption Scheme for secure messaging and file storage
|
|
12
|
+
- **Homomorphic Encryption**: Paillier keys derived from ECDH keypairs for secure voting and computation
|
|
13
|
+
- **Brokered Anonymity**: Forward Error Correction with quorum-based identity recovery
|
|
14
|
+
|
|
15
|
+
### 📦 Owner-Free File System (OFFS)
|
|
16
|
+
- **TUPLE Storage**: All data stored as 3-block TUPLEs (data + 2 randomizers) for complete plausible deniability
|
|
17
|
+
- **Block-based Storage**: Files broken into encrypted blocks with XOR randomization
|
|
18
|
+
- **Deduplication**: SHA-512 based block identification prevents duplicate storage
|
|
19
|
+
- **Distributed Architecture**: Decentralized storage with no single point of failure
|
|
20
|
+
- **Legal Protection**: True owner-free storage ensures no single party can be compelled to produce meaningful data
|
|
21
|
+
|
|
22
|
+
### ⚡ Energy-Efficient Design
|
|
23
|
+
- **Joule Currency**: All operations measured in actual energy consumption
|
|
24
|
+
- **Proof of Work Throttling**: Bad actors face increased computational requirements
|
|
25
|
+
- **Sustainable Operations**: Optimized for minimal energy consumption
|
|
26
|
+
|
|
27
|
+
## 🚀 Quick Start
|
|
28
|
+
|
|
29
|
+
### Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install @brightchain/brightchain-lib
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Basic Usage
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { BrightChain, BlockSize } from '@brightchain/brightchain-lib';
|
|
39
|
+
|
|
40
|
+
// Initialize BrightChain
|
|
41
|
+
const brightChain = new BrightChain(BlockSize.Small);
|
|
42
|
+
|
|
43
|
+
// Store a file
|
|
44
|
+
const fileData = new TextEncoder().encode("Hello, BrightChain!");
|
|
45
|
+
const receipt = await brightChain.storeFile(fileData, "greeting.txt");
|
|
46
|
+
|
|
47
|
+
console.log(`File stored with ID: ${receipt.id}`);
|
|
48
|
+
console.log(`Magnet URL: ${receipt.magnetUrl}`);
|
|
49
|
+
|
|
50
|
+
// Retrieve the file
|
|
51
|
+
const retrievedData = await brightChain.retrieveFile(receipt);
|
|
52
|
+
const retrievedText = new TextDecoder().decode(retrievedData);
|
|
53
|
+
console.log(`Retrieved: ${retrievedText}`);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 📚 Core Concepts
|
|
57
|
+
|
|
58
|
+
### Block Types
|
|
59
|
+
|
|
60
|
+
BrightChain supports several block types for different use cases:
|
|
61
|
+
|
|
62
|
+
- **RawDataBlock**: Unencrypted data blocks
|
|
63
|
+
- **EncryptedBlock**: ECIES-encrypted blocks with single or multiple recipients
|
|
64
|
+
- **ConstituentBlockList (CBL)**: Metadata blocks that reference other blocks
|
|
65
|
+
- **EphemeralBlock**: Temporary blocks for processing
|
|
66
|
+
- **WhitenedBlock**: XOR-randomized blocks for anonymization
|
|
67
|
+
|
|
68
|
+
### Block Sizes
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import { BlockSize } from '@brightchain/brightchain-lib';
|
|
72
|
+
|
|
73
|
+
// Available block sizes
|
|
74
|
+
BlockSize.Tiny // 1024 bytes
|
|
75
|
+
BlockSize.Small // 8192 bytes
|
|
76
|
+
BlockSize.Medium // 32768 bytes
|
|
77
|
+
BlockSize.Large // 131072 bytes
|
|
78
|
+
BlockSize.Huge // 524288 bytes
|
|
79
|
+
BlockSize.Message // 1024 bytes (alias for Tiny)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Encryption Types
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { BlockEncryptionType } from '@brightchain/brightchain-lib';
|
|
86
|
+
|
|
87
|
+
BlockEncryptionType.None // No encryption
|
|
88
|
+
BlockEncryptionType.SingleRecipient // Single recipient ECIES
|
|
89
|
+
BlockEncryptionType.MultiRecipient // Multiple recipient ECIES
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## 🔧 Advanced Usage
|
|
93
|
+
|
|
94
|
+
### Error Handling
|
|
95
|
+
|
|
96
|
+
BrightChain v2.0 introduces a unified error handling system with rich context and type safety:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
import {
|
|
100
|
+
BrightChainError,
|
|
101
|
+
ValidationError,
|
|
102
|
+
ChecksumError,
|
|
103
|
+
FactoryPatternViolationError,
|
|
104
|
+
isValidationError,
|
|
105
|
+
isChecksumError,
|
|
106
|
+
isBrightChainError
|
|
107
|
+
} from '@brightchain/brightchain-lib';
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
// Perform operations
|
|
111
|
+
const block = await blockService.createBlock(params);
|
|
112
|
+
} catch (error) {
|
|
113
|
+
// Type-safe error handling with type guards
|
|
114
|
+
if (isValidationError(error)) {
|
|
115
|
+
console.error(`Validation failed for field: ${error.field}`);
|
|
116
|
+
console.error(`Message: ${error.message}`);
|
|
117
|
+
console.error(`Context:`, error.context);
|
|
118
|
+
} else if (isChecksumError(error)) {
|
|
119
|
+
console.error(`Checksum error type: ${error.checksumErrorType}`);
|
|
120
|
+
console.error(`Message: ${error.message}`);
|
|
121
|
+
} else if (isBrightChainError(error)) {
|
|
122
|
+
// Generic BrightChain error
|
|
123
|
+
console.error(`Error type: ${error.type}`);
|
|
124
|
+
console.error(`Message: ${error.message}`);
|
|
125
|
+
console.error(`Context:`, error.context);
|
|
126
|
+
|
|
127
|
+
// Check for underlying cause
|
|
128
|
+
if (error.cause) {
|
|
129
|
+
console.error(`Caused by:`, error.cause);
|
|
130
|
+
}
|
|
131
|
+
} else {
|
|
132
|
+
// Non-BrightChain error
|
|
133
|
+
console.error('Unexpected error:', error);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Error Types:**
|
|
139
|
+
- `BrightChainError`: Base class for all BrightChain errors
|
|
140
|
+
- `ValidationError`: Input validation failures
|
|
141
|
+
- `ChecksumError`: Checksum calculation or validation errors
|
|
142
|
+
- `FactoryPatternViolationError`: Attempted direct instantiation of factory-only classes
|
|
143
|
+
- `BlockCapacityError`: Block capacity calculation errors
|
|
144
|
+
- `ExtendedCblError`: Extended CBL validation errors
|
|
145
|
+
|
|
146
|
+
**Error Context:**
|
|
147
|
+
All BrightChain errors include:
|
|
148
|
+
- `type`: Error type identifier
|
|
149
|
+
- `message`: Human-readable error message
|
|
150
|
+
- `context`: Additional context (parameters, state, etc.)
|
|
151
|
+
- `cause`: Original error if this error wraps another
|
|
152
|
+
|
|
153
|
+
### Type System
|
|
154
|
+
|
|
155
|
+
BrightChain v2.0 introduces improved type safety with the `Checksum` class and typed `BlockHandle`:
|
|
156
|
+
|
|
157
|
+
#### Checksum Class
|
|
158
|
+
|
|
159
|
+
The unified `Checksum` class replaces separate `ChecksumBuffer` and `ChecksumUint8Array` types:
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
import { Checksum } from '@brightchain/brightchain-lib';
|
|
163
|
+
|
|
164
|
+
// Create from different sources
|
|
165
|
+
const checksumFromBuffer = Checksum.fromBuffer(buffer);
|
|
166
|
+
const checksumFromArray = Checksum.fromUint8Array(uint8Array);
|
|
167
|
+
const checksumFromHex = Checksum.fromHex('abc123...');
|
|
168
|
+
|
|
169
|
+
// Compare checksums
|
|
170
|
+
if (checksum1.equals(checksum2)) {
|
|
171
|
+
console.log('Checksums match!');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Convert to different formats
|
|
175
|
+
const buffer = checksum.toBuffer();
|
|
176
|
+
const array = checksum.toUint8Array();
|
|
177
|
+
const hex = checksum.toHex();
|
|
178
|
+
const str = checksum.toString(); // Same as toHex()
|
|
179
|
+
|
|
180
|
+
// Use with services
|
|
181
|
+
const checksumService = ServiceProvider.getInstance().checksumService;
|
|
182
|
+
const checksum = checksumService.calculateChecksumAsClass(data);
|
|
183
|
+
console.log(`Checksum: ${checksum.toHex()}`);
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
#### Typed BlockHandle
|
|
187
|
+
|
|
188
|
+
`BlockHandle<T>` now requires a type parameter for full type safety:
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
import { BlockHandle, BaseBlock, RawDataBlock } from '@brightchain/brightchain-lib';
|
|
192
|
+
|
|
193
|
+
// Type-safe block handles
|
|
194
|
+
const baseHandle: BlockHandle<BaseBlock> = ...;
|
|
195
|
+
const rawDataHandle: BlockHandle<RawDataBlock> = ...;
|
|
196
|
+
|
|
197
|
+
// TypeScript enforces type safety
|
|
198
|
+
function processBlock(handle: BlockHandle<RawDataBlock>) {
|
|
199
|
+
// TypeScript knows this is a RawDataBlock handle
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Compile-time error if type parameter is missing
|
|
203
|
+
// const handle: BlockHandle = ...; // ❌ Error: Type parameter required
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Factory Patterns
|
|
207
|
+
|
|
208
|
+
BrightChain enforces factory patterns at runtime to ensure proper object initialization:
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
import { MemberDocument, FactoryPatternViolationError } from '@brightchain/brightchain-lib';
|
|
212
|
+
|
|
213
|
+
// ✅ Correct: Use factory method
|
|
214
|
+
const member = MemberDocument.create(
|
|
215
|
+
publicMember,
|
|
216
|
+
privateMember,
|
|
217
|
+
data
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
// ❌ Incorrect: Direct instantiation throws error
|
|
221
|
+
try {
|
|
222
|
+
const member = new MemberDocument(...); // Throws FactoryPatternViolationError
|
|
223
|
+
} catch (error) {
|
|
224
|
+
if (error instanceof FactoryPatternViolationError) {
|
|
225
|
+
console.error('Use factory method instead:', error.message);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**Classes with Factory Patterns:**
|
|
231
|
+
- `MemberDocument`: Use `MemberDocument.create()`
|
|
232
|
+
- `BaseBlock` subclasses: Use `BlockType.from()` or specific factory methods
|
|
233
|
+
- `Checksum`: Use `Checksum.fromBuffer()`, `Checksum.fromUint8Array()`, or `Checksum.fromHex()`
|
|
234
|
+
|
|
235
|
+
**Why Factory Patterns?**
|
|
236
|
+
- Ensures proper validation during object creation
|
|
237
|
+
- Prevents invalid object states
|
|
238
|
+
- Provides clear, documented creation APIs
|
|
239
|
+
- Enables future enhancements without breaking changes
|
|
240
|
+
|
|
241
|
+
### Migration from v1.x to v2.0
|
|
242
|
+
|
|
243
|
+
If you're upgrading from BrightChain v1.x, see our comprehensive [Migration Guide](./MIGRATION.md) for:
|
|
244
|
+
|
|
245
|
+
- Step-by-step migration instructions
|
|
246
|
+
- Before/after code examples
|
|
247
|
+
- Automated migration scripts
|
|
248
|
+
- Deprecation timeline
|
|
249
|
+
- Breaking changes documentation
|
|
250
|
+
|
|
251
|
+
**Quick Migration Checklist:**
|
|
252
|
+
- [ ] Replace `ChecksumBuffer`/`ChecksumUint8Array` with `Checksum` class
|
|
253
|
+
- [ ] Update direct constructor calls to use factory methods
|
|
254
|
+
- [ ] Add type parameters to `BlockHandle` declarations
|
|
255
|
+
- [ ] Update property names (`typeSpecificHeader` → `typeSpecificOverhead`, `payload` → `data`)
|
|
256
|
+
- [ ] Update error handling to use new error types and type guards
|
|
257
|
+
|
|
258
|
+
See [MIGRATION.md](./MIGRATION.md) for complete details.
|
|
259
|
+
|
|
260
|
+
### TUPLE Storage
|
|
261
|
+
|
|
262
|
+
BrightChain v2.1+ implements complete Owner-Free Filesystem compliance through TUPLE storage:
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
import { TupleStorageService, BlockSize } from '@brightchain/brightchain-lib';
|
|
266
|
+
|
|
267
|
+
// Initialize TUPLE storage service
|
|
268
|
+
const blockStore = ...; // Your block store instance
|
|
269
|
+
const tupleService = new TupleStorageService(blockStore);
|
|
270
|
+
|
|
271
|
+
// Store data as a TUPLE (3 blocks: data ⊕ R1 ⊕ R2, R1, R2)
|
|
272
|
+
const data = new TextEncoder().encode("Sensitive information");
|
|
273
|
+
const result = await tupleService.storeTuple(data, {
|
|
274
|
+
durabilityLevel: DurabilityLevel.High,
|
|
275
|
+
expiresAt: new Date(Date.now() + 86400000), // 24 hours
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
console.log('TUPLE Magnet URL:', result.magnetUrl);
|
|
279
|
+
// magnet:?xt=urn:brightchain:tuple&bs=1024&d=abc...&r1=def...&r2=ghi...
|
|
280
|
+
|
|
281
|
+
// Retrieve original data from TUPLE
|
|
282
|
+
const components = tupleService.parseTupleMagnetUrl(result.magnetUrl);
|
|
283
|
+
const originalData = await tupleService.retrieveTuple(
|
|
284
|
+
components.dataBlockId,
|
|
285
|
+
components.randomizerBlockIds,
|
|
286
|
+
components.parityBlockIds,
|
|
287
|
+
);
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
**Why TUPLEs?**
|
|
291
|
+
- **Plausible Deniability**: No single block contains identifiable data
|
|
292
|
+
- **Legal Protection**: Node operators cannot be compelled to produce meaningful data
|
|
293
|
+
- **Complete OFF Compliance**: All data stored as 3 blocks (not just 2)
|
|
294
|
+
- **Brokered Anonymity**: Supports quorum-based identity recovery
|
|
295
|
+
|
|
296
|
+
See [TUPLE Storage Architecture](../../docs/TUPLE_Storage_Architecture.md) for complete details.
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
import {
|
|
300
|
+
EncryptedBlock,
|
|
301
|
+
BlockType,
|
|
302
|
+
BlockDataType,
|
|
303
|
+
BlockSize,
|
|
304
|
+
Member,
|
|
305
|
+
MemberType
|
|
306
|
+
} from '@brightchain/brightchain-lib';
|
|
307
|
+
|
|
308
|
+
// Create a member (user) with cryptographic keys
|
|
309
|
+
const eciesService = ServiceProvider.getInstance().eciesService;
|
|
310
|
+
const member = Member.newMember(
|
|
311
|
+
eciesService,
|
|
312
|
+
MemberType.User,
|
|
313
|
+
'Alice',
|
|
314
|
+
new EmailString('alice@example.com')
|
|
315
|
+
).member;
|
|
316
|
+
|
|
317
|
+
// Create encrypted data
|
|
318
|
+
const plaintext = new TextEncoder().encode("Secret message");
|
|
319
|
+
const encryptedData = await eciesService.encryptSimpleOrSingle(
|
|
320
|
+
true,
|
|
321
|
+
member.publicKey,
|
|
322
|
+
plaintext
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
// Create encrypted block
|
|
326
|
+
const block = await EncryptedBlock.from(
|
|
327
|
+
BlockType.EncryptedOwnedDataBlock,
|
|
328
|
+
BlockDataType.EncryptedData,
|
|
329
|
+
BlockSize.Small,
|
|
330
|
+
encryptedData,
|
|
331
|
+
checksumService.calculateChecksum(encryptedData),
|
|
332
|
+
member
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
// Decrypt the block
|
|
336
|
+
const decryptedBlock = await block.decrypt(BlockType.RawDataBlock);
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Constituent Block Lists (CBL)
|
|
340
|
+
|
|
341
|
+
CBLs are metadata blocks that reference other blocks, enabling complex file structures:
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
import { ConstituentBlockListBlock, CBLService } from '@brightchain/brightchain-lib';
|
|
345
|
+
|
|
346
|
+
const cblService = ServiceProvider.getInstance().cblService;
|
|
347
|
+
|
|
348
|
+
// Calculate capacity for CBL blocks
|
|
349
|
+
const capacity = cblService.calculateCBLAddressCapacity(
|
|
350
|
+
BlockSize.Medium,
|
|
351
|
+
BlockEncryptionType.SingleRecipient
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
console.log(`CBL can hold ${capacity} block references`);
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### TCBL Archives (Tarball CBL)
|
|
358
|
+
|
|
359
|
+
TCBL is a tarball-like archive format built on top of CBL. It bundles multiple files into a single block with a manifest, supporting optional bzip2 compression and external ECIES encryption via the `EncryptedBlock` wrapper.
|
|
360
|
+
|
|
361
|
+
#### Building a TCBL Archive
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
import {
|
|
365
|
+
TcblBuilder,
|
|
366
|
+
TcblReader,
|
|
367
|
+
BlockSize,
|
|
368
|
+
} from '@brightchain/brightchain-lib';
|
|
369
|
+
|
|
370
|
+
// Create a builder
|
|
371
|
+
const builder = new TcblBuilder(creator, BlockSize.Small, blockStore);
|
|
372
|
+
|
|
373
|
+
// Add entries
|
|
374
|
+
await builder.addEntry({
|
|
375
|
+
fileName: 'readme.txt',
|
|
376
|
+
mimeType: 'text/plain',
|
|
377
|
+
data: new TextEncoder().encode('Hello, TCBL!'),
|
|
378
|
+
});
|
|
379
|
+
await builder.addEntry({
|
|
380
|
+
fileName: 'config.json',
|
|
381
|
+
mimeType: 'application/json',
|
|
382
|
+
data: new TextEncoder().encode('{"key": "value"}'),
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
// Build the archive (with optional compression)
|
|
386
|
+
const tcblBlock = await builder.build();
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
#### Reading a TCBL Archive
|
|
390
|
+
|
|
391
|
+
```typescript
|
|
392
|
+
// Open the archive for reading
|
|
393
|
+
const reader = new TcblReader(tcblBlock, blockStore);
|
|
394
|
+
await reader.open();
|
|
395
|
+
|
|
396
|
+
// List entries without extracting data
|
|
397
|
+
const entries = reader.listEntries();
|
|
398
|
+
for (const entry of entries) {
|
|
399
|
+
console.log(`${entry.fileName} (${entry.mimeType}, ${entry.originalDataLength} bytes)`);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Extract by name or index
|
|
403
|
+
const data = await reader.getEntryByName('readme.txt');
|
|
404
|
+
const firstEntry = await reader.getEntryByIndex(0);
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
#### Compression and Encryption
|
|
408
|
+
|
|
409
|
+
```typescript
|
|
410
|
+
// Enable bzip2 compression
|
|
411
|
+
const builder = new TcblBuilder(creator, BlockSize.Small, blockStore, undefined, {
|
|
412
|
+
compress: true,
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
// For encryption, wrap the completed TCBL in an EncryptedBlock
|
|
416
|
+
const tcbl = await builder.build();
|
|
417
|
+
const encrypted = await EncryptedBlockCreator.from(
|
|
418
|
+
tcbl,
|
|
419
|
+
recipientPublicKeys,
|
|
420
|
+
);
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Service Provider Pattern
|
|
424
|
+
|
|
425
|
+
BrightChain uses a service provider pattern for dependency injection:
|
|
426
|
+
|
|
427
|
+
```typescript
|
|
428
|
+
import { ServiceProvider } from '@brightchain/brightchain-lib';
|
|
429
|
+
|
|
430
|
+
// Get service instances
|
|
431
|
+
const provider = ServiceProvider.getInstance();
|
|
432
|
+
const checksumService = provider.checksumService;
|
|
433
|
+
const eciesService = provider.eciesService;
|
|
434
|
+
const blockService = provider.blockService;
|
|
435
|
+
|
|
436
|
+
// Calculate checksums
|
|
437
|
+
const data = new Uint8Array([1, 2, 3, 4]);
|
|
438
|
+
const checksum = checksumService.calculateChecksum(data);
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
## 🏗️ Architecture
|
|
442
|
+
|
|
443
|
+
### Block Structure
|
|
444
|
+
|
|
445
|
+
All blocks follow a layered structure:
|
|
446
|
+
|
|
447
|
+
```
|
|
448
|
+
[Base Header][Layer Headers][Layer Data][Padding]
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
**Base Header includes:**
|
|
452
|
+
- Block Type
|
|
453
|
+
- Block Size
|
|
454
|
+
- Data Type
|
|
455
|
+
- Checksum
|
|
456
|
+
- Date Created
|
|
457
|
+
|
|
458
|
+
**Encrypted Block Header adds:**
|
|
459
|
+
- Encryption Type (1 byte)
|
|
460
|
+
- Recipient GUID (16 bytes)
|
|
461
|
+
- Ephemeral Public Key (65 bytes)
|
|
462
|
+
- IV (16 bytes)
|
|
463
|
+
- Auth Tag (16 bytes)
|
|
464
|
+
|
|
465
|
+
### Storage Architecture
|
|
466
|
+
|
|
467
|
+
```mermaid
|
|
468
|
+
graph TD
|
|
469
|
+
A[File Input] --> B[Block Splitter]
|
|
470
|
+
B --> C[XOR with Random Blocks]
|
|
471
|
+
C --> D[Encrypted Blocks]
|
|
472
|
+
D --> E[Block Store]
|
|
473
|
+
E --> F[CBL Creation]
|
|
474
|
+
F --> G[Magnet URL]
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
## 🔒 Security Features
|
|
478
|
+
|
|
479
|
+
### Brokered Anonymity
|
|
480
|
+
|
|
481
|
+
BrightChain provides privacy through Forward Error Correction:
|
|
482
|
+
|
|
483
|
+
1. **Identity Replacement**: Real identities replaced with FEC datasets
|
|
484
|
+
2. **Quorum Distribution**: Identity shards distributed among trusted agents
|
|
485
|
+
3. **Majority Recovery**: Requires quorum majority to recover identity
|
|
486
|
+
4. **Digital Statute of Limitations**: FEC data expires after predetermined time
|
|
487
|
+
|
|
488
|
+
### Cryptographic Guarantees
|
|
489
|
+
|
|
490
|
+
- **ECIES Security**: Elliptic curve cryptography with AES-256-GCM
|
|
491
|
+
- **Homomorphic Voting**: Paillier encryption for private voting
|
|
492
|
+
- **Block Integrity**: SHA-512 checksums for all blocks
|
|
493
|
+
- **Forward Secrecy**: Temporal key rotation support
|
|
494
|
+
|
|
495
|
+
## 📊 Constants and Configuration
|
|
496
|
+
|
|
497
|
+
### Core Constants
|
|
498
|
+
|
|
499
|
+
```typescript
|
|
500
|
+
import CONSTANTS from '@brightchain/brightchain-lib';
|
|
501
|
+
|
|
502
|
+
// ECIES Configuration
|
|
503
|
+
CONSTANTS.ECIES.CURVE_NAME // 'secp256k1'
|
|
504
|
+
CONSTANTS.ECIES.PUBLIC_KEY_LENGTH // 65 bytes
|
|
505
|
+
CONSTANTS.ECIES.PRIVATE_KEY_LENGTH // 32 bytes
|
|
506
|
+
|
|
507
|
+
// Block Configuration
|
|
508
|
+
CONSTANTS.CBL.MAX_FILE_NAME_LENGTH // 255 characters
|
|
509
|
+
CONSTANTS.TUPLE.SIZE // 3 blocks per tuple
|
|
510
|
+
CONSTANTS.FEC.MAX_SHARD_SIZE // 1MB
|
|
511
|
+
|
|
512
|
+
// Encryption Settings
|
|
513
|
+
CONSTANTS.ENCRYPTION.RECIPIENT_ID_SIZE // 16 bytes
|
|
514
|
+
CONSTANTS.ENCRYPTION.ENCRYPTION_TYPE_SIZE // 1 byte
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### ECIES Configuration
|
|
518
|
+
|
|
519
|
+
```typescript
|
|
520
|
+
import { EciesConfig } from '@brightchain/brightchain-lib';
|
|
521
|
+
|
|
522
|
+
const config = EciesConfig;
|
|
523
|
+
console.log(config.curveName); // 'secp256k1'
|
|
524
|
+
console.log(config.symmetricAlgorithm); // 'aes-256-gcm'
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
## 🧪 Testing
|
|
528
|
+
|
|
529
|
+
### Running Tests
|
|
530
|
+
|
|
531
|
+
```bash
|
|
532
|
+
# Run all tests
|
|
533
|
+
npm test
|
|
534
|
+
|
|
535
|
+
# Run with specific configuration
|
|
536
|
+
npm run test:dev:16
|
|
537
|
+
|
|
538
|
+
# Run with logging
|
|
539
|
+
npm run test:dev:16:logged
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
### Test Structure
|
|
543
|
+
|
|
544
|
+
The library includes comprehensive tests:
|
|
545
|
+
|
|
546
|
+
- **Unit Tests**: Individual component testing
|
|
547
|
+
- **Integration Tests**: Service interaction testing
|
|
548
|
+
- **Property Tests**: Cryptographic property verification
|
|
549
|
+
- **System Tests**: End-to-end functionality testing
|
|
550
|
+
|
|
551
|
+
## 🔧 Development
|
|
552
|
+
|
|
553
|
+
### Building
|
|
554
|
+
|
|
555
|
+
```bash
|
|
556
|
+
# Development build
|
|
557
|
+
npm run build:dev
|
|
558
|
+
|
|
559
|
+
# Production build (via Nx)
|
|
560
|
+
npx nx build brightchain-lib
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
### Linting
|
|
564
|
+
|
|
565
|
+
```bash
|
|
566
|
+
# Check code style
|
|
567
|
+
npm run lint
|
|
568
|
+
|
|
569
|
+
# Fix code style issues
|
|
570
|
+
npm run lint:fix
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
## 🌐 Browser Compatibility
|
|
574
|
+
|
|
575
|
+
BrightChain is designed to work in both Node.js and browser environments:
|
|
576
|
+
|
|
577
|
+
```typescript
|
|
578
|
+
// Browser-specific entry point
|
|
579
|
+
import { BrightChain } from '@brightchain/brightchain-lib/browser';
|
|
580
|
+
|
|
581
|
+
// Node.js entry point
|
|
582
|
+
import { BrightChain } from '@brightchain/brightchain-lib';
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
## 📖 API Reference
|
|
586
|
+
|
|
587
|
+
For detailed naming conventions and terminology, see [NAMING_CONVENTIONS.md](./NAMING_CONVENTIONS.md).
|
|
588
|
+
|
|
589
|
+
### Core Classes
|
|
590
|
+
|
|
591
|
+
#### BrightChain
|
|
592
|
+
Main interface for file storage and retrieval.
|
|
593
|
+
|
|
594
|
+
**Methods:**
|
|
595
|
+
- `storeFile(data: Uint8Array, fileName?: string): Promise<FileReceipt>`
|
|
596
|
+
- `retrieveFile(receipt: FileReceipt): Promise<Uint8Array>`
|
|
597
|
+
|
|
598
|
+
#### BaseBlock
|
|
599
|
+
Abstract base class for all block types.
|
|
600
|
+
|
|
601
|
+
**Properties:**
|
|
602
|
+
- `blockSize: BlockSize` - Size category of the block
|
|
603
|
+
- `blockType: BlockType` - Type of block (raw, encrypted, CBL, etc)
|
|
604
|
+
- `idChecksum: ChecksumUint8Array` - Unique identifier
|
|
605
|
+
- `dateCreated: Date` - Creation timestamp
|
|
606
|
+
|
|
607
|
+
**Methods:**
|
|
608
|
+
- `validateAsync(): Promise<void>` - Async validation
|
|
609
|
+
- `validateSync(): void` - Sync validation
|
|
610
|
+
|
|
611
|
+
#### EncryptedBlock
|
|
612
|
+
Encrypted block implementation with ECIES.
|
|
613
|
+
|
|
614
|
+
**Properties:**
|
|
615
|
+
- `encryptionType: BlockEncryptionType` - Single or multi-recipient
|
|
616
|
+
- `recipients: Array<TID>` - List of recipient IDs
|
|
617
|
+
- `recipientWithKey: Member<TID>` - Member with decryption key
|
|
618
|
+
|
|
619
|
+
**Methods:**
|
|
620
|
+
- `decrypt<D>(newBlockType: BlockType): Promise<D>` - Decrypt block
|
|
621
|
+
|
|
622
|
+
### Services
|
|
623
|
+
|
|
624
|
+
#### ChecksumService
|
|
625
|
+
Handles SHA-512 checksum operations.
|
|
626
|
+
|
|
627
|
+
**Methods:**
|
|
628
|
+
- `calculateChecksum(data: Uint8Array): ChecksumUint8Array`
|
|
629
|
+
- `checksumToHexString(checksum: ChecksumUint8Array): ChecksumString`
|
|
630
|
+
|
|
631
|
+
#### ECIESService
|
|
632
|
+
Provides ECIES encryption/decryption.
|
|
633
|
+
|
|
634
|
+
**Methods:**
|
|
635
|
+
- `encryptSimpleOrSingle(simple: boolean, publicKey: Uint8Array, data: Uint8Array): Promise<Uint8Array>`
|
|
636
|
+
- `decryptSimpleOrSingle(simple: boolean, privateKey: Uint8Array, data: Uint8Array): Promise<Uint8Array>`
|
|
637
|
+
|
|
638
|
+
## 🤝 Contributing
|
|
639
|
+
|
|
640
|
+
We welcome contributions! Please see our [Contributing Guide](../CONTRIBUTING.md) for details.
|
|
641
|
+
|
|
642
|
+
### Development Setup
|
|
643
|
+
|
|
644
|
+
1. Clone the repository
|
|
645
|
+
2. Install dependencies: `yarn install`
|
|
646
|
+
3. Run tests: `npm test`
|
|
647
|
+
4. Build: `npm run build:dev`
|
|
648
|
+
|
|
649
|
+
## 📄 License
|
|
650
|
+
|
|
651
|
+
This project is licensed under the MIT License - see the [LICENSE](../LICENSE) file for details.
|
|
652
|
+
|
|
653
|
+
## 🔗 Related Projects
|
|
654
|
+
|
|
655
|
+
- **@digitaldefiance/ecies-lib**: Core cryptographic primitives
|
|
656
|
+
- **@digitaldefiance/i18n-lib**: Internationalization support
|
|
657
|
+
- **brightchain-api**: REST API server
|
|
658
|
+
- **brightchain-react**: React frontend components
|
|
659
|
+
|
|
660
|
+
## 📞 Support
|
|
661
|
+
|
|
662
|
+
- **GitHub Issues**: [Report bugs or request features](https://github.com/Digital-Defiance/BrightChain/issues)
|
|
663
|
+
- **Documentation**: [Full documentation](https://github.com/Digital-Defiance/BrightChain#readme)
|
|
664
|
+
- **Community**: [Join our discussions](https://github.com/Digital-Defiance/BrightChain/discussions)
|
|
665
|
+
|
|
666
|
+
## 🎯 Roadmap
|
|
667
|
+
|
|
668
|
+
BrightChain is actively developed with ambitious goals:
|
|
669
|
+
|
|
670
|
+
- **Phase 1**: Complete Owner-Free File System ✅
|
|
671
|
+
- **Phase 2**: Identity and reputation systems (In Progress)
|
|
672
|
+
- **Phase 3**: Digital contracts and governance
|
|
673
|
+
- **Phase 4**: Global adoption and interplanetary standards
|
|
674
|
+
|
|
675
|
+
---
|
|
676
|
+
|
|
677
|
+
**BrightChain** - *Illuminating the future of decentralized digital governance*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brightchain/brightchain-lib",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "BrightChain core library - browser-compatible blockchain storage",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "src/index.d.ts",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"author": "Digital Defiance",
|
|
42
42
|
"license": "MIT",
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@digitaldefiance/ecies-lib": "^4.19.
|
|
44
|
+
"@digitaldefiance/ecies-lib": "^4.19.11",
|
|
45
45
|
"@digitaldefiance/i18n-lib": "^4.6.4",
|
|
46
46
|
"@noble/hashes": "^1.4.0",
|
|
47
47
|
"nat-pmp": "^1.0.0",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../brightchain-lib/src/lib/blocks/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,OAAO,CAAC;AACtB,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../brightchain-lib/src/lib/blocks/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,OAAO,CAAC;AACtB,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC"}
|