1- import * as cbor from 'cbor' ;
2- import * as crypto from 'crypto' ;
3- import * as multibase from 'multibase' ;
4- import { BaseNameOrCode } from 'multibase' ;
5-
6- export let ChunkSize = 2048 * 1024 ; // 2 megabytes
7-
8- export enum LeafType {
9- FileLeaf = "file" ,
10- ChunkLeaf = "chunk" ,
11- DirectoryLeaf = "directory"
12- }
13-
14- export interface DagBuilder {
15- Leafs : Record < string , DagLeaf > ;
16- }
17-
18- export interface DagLeafBuilder {
19- Name : string ;
20- Label : number ;
21- LeafType : LeafType ;
22- Data : Uint8Array ;
23- Links : Record < string , string > ;
24- }
25-
26- export interface Dag {
27- Root : string ;
28- Leafs : Record < string , DagLeaf > ;
29-
30- getDataFromLeaf ( leaf : DagLeaf ) : [ Uint8Array , any ] ;
31- verify ( encoder : BaseNameOrCode ) : Promise < [ boolean , any ] > ;
32- }
33-
34- export interface DagLeaf {
35- Hash : string ;
36- Name : string ;
37- Type : LeafType ;
38- Data : Uint8Array ;
39- MerkleRoot : Uint8Array ;
40- CurrentLinkCount : number ;
41- LatestLabel : string ;
42- LeafCount : number ;
43- Links : Record < string , string > ;
44- ParentHash : string ;
45-
46- hasLink ( hash : string ) : boolean ;
47- addLink ( hash : string ) : void ;
48- clone ( ) : DagLeaf ;
49- setLabel ( label : string ) : void ;
50- verifyLeaf ( encoder : BaseNameOrCode ) : Promise < [ boolean , any ] >
51- verifyRootLeaf ( encoder : BaseNameOrCode ) : Promise < [ boolean , any ] >
52- }
53-
54- export function setChunkSize ( size : number ) {
55- ChunkSize = size ;
56- }
57-
58- export function CreateDagLeafBuilder ( name : string ) : DagLeafBuilder {
59- return new DagLeafBuilder ( name ) ;
60- }
61-
62- export function hasLabel ( hash : string ) : boolean {
63- return getLabel ( hash ) !== "" ;
64- }
65-
66- export function getHash ( hash : string ) : string {
67- const parts = hash . split ( ":" ) ;
68- if ( parts . length !== 2 ) return hash ;
69- return parts [ 1 ] ;
70- }
71-
72- export function getLabel ( hash : string ) : string {
73- const parts = hash . split ( ":" ) ;
74- if ( parts . length !== 2 ) return "" ;
75- return parts [ 0 ] ;
76- }
77-
78- export class DagLeafBuilder {
79- Name : string ;
80- Label ! : number ;
81- LeafType ! : LeafType ;
82- Data ! : Uint8Array ;
83- Links : Record < string , string > = { } ;
84-
85- constructor ( name : string ) {
86- this . Name = name ;
87- }
88-
89- setType ( leafType : LeafType ) : void {
90- this . LeafType = leafType ;
91- }
92-
93- setData ( data : Uint8Array ) : void {
94- this . Data = data ;
95- }
96-
97- addLink ( label : string , hash : string ) : void {
98- this . Links [ label ] = `${ label } :${ hash } ` ;
99- }
100- }
101-
102- export class DagLeaf implements DagLeaf {
103- Hash ! : string ;
104- Name ! : string ;
105- Type ! : LeafType ;
106- Data ! : Uint8Array ;
107- MerkleRoot ! : Uint8Array ;
108- CurrentLinkCount ! : number ;
109- LatestLabel ! : string ;
110- LeafCount ! : number ;
111- Links ! : Record < string , string > ;
112- ParentHash ! : string ;
113-
114- constructor ( leaf : DagLeaf ) {
115- Object . assign ( this , leaf ) ;
116- }
117-
118- hasLink ( hash : string ) : boolean {
119- for ( const label of Object . keys ( this . Links ) ) {
120- const link = this . Links [ label ]
121-
122- if ( hasLabel ( hash ) ) {
123- if ( hasLabel ( link ) ) {
124- if ( link === hash ) return true ;
125- } else {
126- if ( link === getHash ( hash ) ) return true ;
127- }
128- } else {
129- if ( hasLabel ( link ) ) {
130- if ( getHash ( link ) === hash ) return true ;
131- } else {
132- if ( getHash ( link ) === getHash ( hash ) ) return true ;
133- }
134- }
135- }
136-
137- return false ;
138- }
139-
140- addLink ( hash : string ) : void {
141- const label = getLabel ( hash ) ;
142-
143- if ( label === "" ) {
144- console . log ( "This hash does not have a label" ) ;
145- }
146-
147- this . Links [ label ] = hash ;
148- }
149-
150- clone ( ) : DagLeaf {
151- return new DagLeaf ( this ) ;
152- }
153-
154- setLabel ( label : string ) : void {
155- this . Hash = `${ label } :${ this . Hash } ` ;
156- }
157-
158- async verifyLeaf ( encoder : BaseNameOrCode ) : Promise < [ boolean , any ] > {
159- const leafData = {
160- Name : this . Name ,
161- Type : this . Type ,
162- MerkleRoot : this . MerkleRoot ,
163- CurrentLinkCount : this . CurrentLinkCount ,
164- Data : this . Data ,
165- } ;
166-
167- try {
168- const serializedLeafData = cbor . encode ( leafData ) ;
169- const hash = crypto . createHash ( 'sha256' ) . update ( serializedLeafData ) . digest ( ) ;
170-
171- let result = false ;
172- if ( hasLabel ( this . Hash ) ) {
173- result = multibase . encode ( encoder , hash ) . toString ( ) === getHash ( this . Hash ) ;
174- } else {
175- result = multibase . encode ( encoder , hash ) . toString ( ) === this . Hash ;
176- }
177-
178- return [ result , null ] ;
179- } catch ( err ) {
180- return [ false , err ] ;
181- }
182- }
183-
184- async verifyRootLeaf ( encoder : BaseNameOrCode ) : Promise < [ boolean , any ] > {
185- const leafData = {
186- Name : this . Name ,
187- Type : this . Type ,
188- MerkleRoot : this . MerkleRoot ,
189- CurrentLinkCount : this . CurrentLinkCount ,
190- LatestLabel : this . LatestLabel ,
191- LeafCount : this . LeafCount ,
192- Data : this . Data ,
193- } ;
194-
195- try {
196- const serializedLeafData = cbor . encode ( leafData ) ;
197- const hash = crypto . createHash ( 'sha256' ) . update ( serializedLeafData ) . digest ( ) ;
198-
199- let result = false ;
200- if ( hasLabel ( this . Hash ) ) {
201- result = multibase . encode ( encoder , hash ) . toString ( ) === getHash ( this . Hash ) ;
202- } else {
203- result = multibase . encode ( encoder , hash ) . toString ( ) === this . Hash ;
204- }
205-
206- return [ result , null ] ;
207- } catch ( err ) {
208- return [ false , err ] ;
209- }
210- }
211- }
212-
213- export class DagBuilder {
214- Leafs : Record < string , DagLeaf > = { } ;
215-
216- static CreateDagBuilder ( ) : DagBuilder {
217- return new DagBuilder ( ) ;
218- }
219-
220- getLatestLabel ( ) : string {
221- let latestLabel : number = 1 ;
222-
223- for ( const hash in this . Leafs ) {
224- const label = getLabel ( hash ) ;
225-
226- if ( label === "" ) {
227- console . log ( "Failed to find label in hash" ) ;
228- }
229-
230- const parsed = parseInt ( label , 10 ) ;
231-
232- if ( parsed > latestLabel ) {
233- latestLabel = parsed ;
234- }
235- }
236-
237- return latestLabel . toString ( ) ;
238- }
239-
240- getNextAvailableLabel ( ) : string {
241- const latestLabel = this . getLatestLabel ( ) ;
242- const number = parseInt ( latestLabel , 10 ) ;
243-
244- const nextLabel = ( number + 1 ) . toString ( ) ;
245-
246- return nextLabel ;
247- }
248-
249- addLeaf ( leaf : DagLeaf , parentLeaf : DagLeaf | null ) : void {
250- if ( parentLeaf !== null ) {
251- const label = getLabel ( leaf . Hash ) ;
252- if ( ! ( label in parentLeaf . Links ) ) {
253- parentLeaf . addLink ( leaf . Hash ) ;
254- }
255- }
256-
257- this . Leafs [ leaf . Hash ] = leaf ;
258- }
259-
260- buildDag ( root : string ) : Dag {
261- return new Dag ( this . Leafs , root ) ;
262- }
263- }
264-
265- export class Dag implements Dag {
266- Leafs : Record < string , DagLeaf > = { } ;
267- Root : string ;
268-
269- constructor ( leafs : Record < string , DagLeaf > , root : string ) {
270- this . Leafs = leafs ;
271- this . Root = root ;
272- }
273-
274- async verify ( encoder : any ) : Promise < [ boolean , any ] > {
275- let result = true ;
276-
277- for ( const leafHash in this . Leafs ) {
278- const leaf = this . Leafs [ leafHash ] ;
279- let leafResult : boolean , err : Error | null ;
280- if ( leaf . Hash === this . Root ) {
281- [ leafResult , err ] = await leaf . verifyRootLeaf ( encoder ) ; // Assuming you have a method verifyRootLeaf in DagLeaf class
282- } else {
283- [ leafResult , err ] = await leaf . verifyLeaf ( encoder ) ; // Assuming you have a method verifyLeaf in DagLeaf class
284- }
285-
286- if ( err ) {
287- return [ false , err ] ;
288- }
289-
290- if ( ! leafResult ) {
291- result = false ;
292- }
293- }
294-
295- return [ result , null ] ;
296- }
297-
298- getDataFromLeaf ( leaf : DagLeaf ) : [ Uint8Array , any ] {
299- if ( leaf . Data . length <= 0 ) {
300- return [ new Uint8Array ( 0 ) , null ] ;
301- }
302-
303- let content = new Uint8Array ( 0 ) ;
304-
305- if ( Object . keys ( leaf . Links ) . length > 0 ) {
306- for ( const label of Object . keys ( leaf . Links ) ) {
307- const linkHash = leaf . Links [ label ]
308- const childLeaf = this . Leafs [ linkHash ] ;
309- if ( ! childLeaf ) {
310- return [ new Uint8Array ( 0 ) , new Error ( `Invalid link: ${ linkHash } ` ) ] ;
311- }
312-
313- content = new Uint8Array ( [ ...content , ...childLeaf . Data ] ) ; // Assuming Data is Uint8Array or similar
314- }
315- } else {
316- content = leaf . Data ;
317- }
318-
319- return [ content , null ] ;
320- }
321- }
1+ export * from './leaves' ;
2+ export * from './types' ;
3+ export * from './serialize' ;
4+ export * from './tree/tree' ;
0 commit comments