@@ -79,6 +79,31 @@ func (b *DagBuilder) GetNextAvailableLabel() string {
7979 return nextLabel
8080}
8181
82+ // CalculateTotalContentSize calculates the total size of actual content (not including metadata)
83+ func (b * DagBuilder ) CalculateTotalContentSize () int64 {
84+ var totalSize int64
85+ for _ , leaf := range b .Leafs {
86+ if leaf .Content != nil {
87+ totalSize += int64 (len (leaf .Content ))
88+ }
89+ }
90+ return totalSize
91+ }
92+
93+ // CalculateTotalDagSize calculates the total size of all serialized leaves in the DAG
94+ func (b * DagBuilder ) CalculateTotalDagSize () (int64 , error ) {
95+ var totalSize int64
96+ for _ , leaf := range b .Leafs {
97+ serializable := leaf .ToSerializable ()
98+ serialized , err := cbor .Marshal (serializable )
99+ if err != nil {
100+ return 0 , fmt .Errorf ("failed to serialize leaf %s: %w" , leaf .Hash , err )
101+ }
102+ totalSize += int64 (len (serialized ))
103+ }
104+ return totalSize , nil
105+ }
106+
82107func (b * DagLeafBuilder ) BuildLeaf (additionalData map [string ]string ) (* DagLeaf , error ) {
83108 if b .LeafType == "" {
84109 err := fmt .Errorf ("leaf must have a type defined" )
@@ -201,15 +226,25 @@ func (b *DagLeafBuilder) BuildRootLeaf(dag *DagBuilder, additionalData map[strin
201226
202227 latestLabel := dag .GetLatestLabel ()
203228
204- additionalData = sortMapByKeys (additionalData )
229+ contentSize := dag .CalculateTotalContentSize ()
230+ if b .Data != nil {
231+ contentSize += int64 (len (b .Data ))
232+ }
205233
206- leafData := struct {
234+ childrenDagSize , err := dag .CalculateTotalDagSize ()
235+ if err != nil {
236+ return nil , fmt .Errorf ("failed to calculate dag size: %w" , err )
237+ }
238+
239+ tempLeafData := struct {
207240 ItemName string
208241 Type LeafType
209242 MerkleRoot []byte
210243 CurrentLinkCount int
211244 LatestLabel string
212245 LeafCount int
246+ ContentSize int64
247+ DagSize int64
213248 ContentHash []byte
214249 AdditionalData []keyValue
215250 }{
@@ -219,13 +254,49 @@ func (b *DagLeafBuilder) BuildRootLeaf(dag *DagBuilder, additionalData map[strin
219254 CurrentLinkCount : len (b .Links ),
220255 LatestLabel : latestLabel ,
221256 LeafCount : len (dag .Leafs ),
257+ ContentSize : contentSize ,
258+ DagSize : 0 ,
222259 ContentHash : nil ,
223260 AdditionalData : sortMapForVerification (additionalData ),
224261 }
225262
226263 if b .Data != nil {
227264 hash := sha256 .Sum256 (b .Data )
228- leafData .ContentHash = hash [:]
265+ tempLeafData .ContentHash = hash [:]
266+ }
267+
268+ tempSerialized , err := cbor .Marshal (tempLeafData )
269+ if err != nil {
270+ return nil , err
271+ }
272+ rootLeafSize := int64 (len (tempSerialized ))
273+
274+ finalDagSize := childrenDagSize + rootLeafSize
275+
276+ additionalData = sortMapByKeys (additionalData )
277+
278+ leafData := struct {
279+ ItemName string
280+ Type LeafType
281+ MerkleRoot []byte
282+ CurrentLinkCount int
283+ LatestLabel string
284+ LeafCount int
285+ ContentSize int64
286+ DagSize int64
287+ ContentHash []byte
288+ AdditionalData []keyValue
289+ }{
290+ ItemName : b .ItemName ,
291+ Type : b .LeafType ,
292+ MerkleRoot : merkleRoot ,
293+ CurrentLinkCount : len (b .Links ),
294+ LatestLabel : latestLabel ,
295+ LeafCount : len (dag .Leafs ),
296+ ContentSize : contentSize ,
297+ DagSize : finalDagSize ,
298+ ContentHash : tempLeafData .ContentHash , // Reuse from temp
299+ AdditionalData : sortMapForVerification (additionalData ),
229300 }
230301
231302 serializedLeafData , err := cbor .Marshal (leafData )
@@ -254,6 +325,8 @@ func (b *DagLeafBuilder) BuildRootLeaf(dag *DagBuilder, additionalData map[strin
254325 CurrentLinkCount : len (b .Links ),
255326 LatestLabel : latestLabel ,
256327 LeafCount : len (dag .Leafs ),
328+ ContentSize : contentSize ,
329+ DagSize : finalDagSize ,
257330 Content : b .Data ,
258331 ContentHash : leafData .ContentHash ,
259332 Links : sortedLinks ,
@@ -449,20 +522,92 @@ func (leaf *DagLeaf) VerifyLeaf() error {
449522 return nil
450523}
451524
452- func (leaf * DagLeaf ) VerifyRootLeaf () error {
525+ func (leaf * DagLeaf ) VerifyRootLeaf (dag * Dag ) error {
453526 additionalData := sortMapByKeys (leaf .AdditionalData )
454527
455528 if leaf .ClassicMerkleRoot == nil || len (leaf .ClassicMerkleRoot ) <= 0 {
456529 leaf .ClassicMerkleRoot = []byte {}
457530 }
458531
532+ var calculatedContentSize int64
533+ var calculatedDagSize int64
534+
535+ isFullDag := dag != nil &&
536+ len (dag .Leafs ) == leaf .LeafCount &&
537+ (leaf .ContentSize != 0 || leaf .DagSize != 0 || leaf .LeafCount == 1 )
538+
539+ if isFullDag {
540+ for _ , dagLeaf := range dag .Leafs {
541+ if dagLeaf .Content != nil {
542+ calculatedContentSize += int64 (len (dagLeaf .Content ))
543+ }
544+ }
545+
546+ rootHash := GetHash (leaf .Hash )
547+ var childrenDagSize int64
548+ for _ , dagLeaf := range dag .Leafs {
549+ if GetHash (dagLeaf .Hash ) == rootHash {
550+ continue
551+ }
552+
553+ serializable := dagLeaf .ToSerializable ()
554+ serialized , err := cbor .Marshal (serializable )
555+ if err != nil {
556+ return fmt .Errorf ("failed to serialize leaf %s for size verification: %w" , dagLeaf .Hash , err )
557+ }
558+ childrenDagSize += int64 (len (serialized ))
559+ }
560+
561+ tempLeafData := struct {
562+ ItemName string
563+ Type LeafType
564+ MerkleRoot []byte
565+ CurrentLinkCount int
566+ LatestLabel string
567+ LeafCount int
568+ ContentSize int64
569+ DagSize int64
570+ ContentHash []byte
571+ AdditionalData []keyValue
572+ }{
573+ ItemName : leaf .ItemName ,
574+ Type : leaf .Type ,
575+ MerkleRoot : leaf .ClassicMerkleRoot ,
576+ CurrentLinkCount : leaf .CurrentLinkCount ,
577+ LatestLabel : leaf .LatestLabel ,
578+ LeafCount : leaf .LeafCount ,
579+ ContentSize : leaf .ContentSize ,
580+ DagSize : 0 ,
581+ ContentHash : leaf .ContentHash ,
582+ AdditionalData : sortMapForVerification (additionalData ),
583+ }
584+
585+ tempSerialized , err := cbor .Marshal (tempLeafData )
586+ if err != nil {
587+ return fmt .Errorf ("failed to serialize root leaf for size verification: %w" , err )
588+ }
589+ rootLeafSize := int64 (len (tempSerialized ))
590+
591+ calculatedDagSize = childrenDagSize + rootLeafSize
592+
593+ if leaf .ContentSize != calculatedContentSize {
594+ return fmt .Errorf ("content size mismatch: stored %d, calculated %d" , leaf .ContentSize , calculatedContentSize )
595+ }
596+
597+ if leaf .DagSize != calculatedDagSize {
598+ return fmt .Errorf ("dag size mismatch: stored %d, calculated %d" , leaf .DagSize , calculatedDagSize )
599+ }
600+ }
601+
459602 leafData := struct {
460603 ItemName string
461604 Type LeafType
462605 MerkleRoot []byte
463606 CurrentLinkCount int
464607 LatestLabel string
465608 LeafCount int
609+ ContentSize int64
610+ DagSize int64
466611 ContentHash []byte
467612 AdditionalData []keyValue
468613 }{
@@ -472,6 +617,8 @@ func (leaf *DagLeaf) VerifyRootLeaf() error {
472617 CurrentLinkCount : leaf .CurrentLinkCount ,
473618 LatestLabel : leaf .LatestLabel ,
474619 LeafCount : leaf .LeafCount ,
620+ ContentSize : leaf .ContentSize ,
621+ DagSize : leaf .DagSize ,
475622 ContentHash : leaf .ContentHash ,
476623 AdditionalData : sortMapForVerification (additionalData ),
477624 }
@@ -622,6 +769,8 @@ func (leaf *DagLeaf) Clone() *DagLeaf {
622769 CurrentLinkCount : leaf .CurrentLinkCount ,
623770 LatestLabel : leaf .LatestLabel ,
624771 LeafCount : leaf .LeafCount ,
772+ ContentSize : leaf .ContentSize ,
773+ DagSize : leaf .DagSize ,
625774 ParentHash : leaf .ParentHash ,
626775 Links : make (map [string ]string ),
627776 AdditionalData : make (map [string ]string ),
0 commit comments