@@ -1500,3 +1500,141 @@ func (packet *BatchedTransmissionPacket) GetRootLeaf() *DagLeaf {
15001500
15011501 return packet .Leaves [0 ]
15021502}
1503+
1504+ // RecomputeLabels reassigns all labels in the DAG in optimal traversal order.
1505+ func (d * Dag ) RecomputeLabels () error {
1506+ if d .Root == "" {
1507+ return fmt .Errorf ("cannot recompute labels: DAG has no root" )
1508+ }
1509+
1510+ if _ , exists := d .Leafs [d .Root ]; ! exists {
1511+ return fmt .Errorf ("cannot recompute labels: root leaf not found" )
1512+ }
1513+
1514+ // Track bare hash -> new label mapping
1515+ labelMapping := make (map [string ]string )
1516+
1517+ // The root never gets a label
1518+ rootBareHash := StripLabel (d .Root )
1519+ labelMapping [rootBareHash ] = "" // Empty label for root
1520+
1521+ // Breadth-first traversal
1522+ currentLabel := 1
1523+ queue := []string {rootBareHash }
1524+ visited := make (map [string ]bool )
1525+ visited [rootBareHash ] = true
1526+
1527+ for len (queue ) > 0 {
1528+ currentBareHash := queue [0 ]
1529+ queue = queue [1 :]
1530+
1531+ // Find the leaf with this bare hash
1532+ var currentLeaf * DagLeaf
1533+ for hash , leaf := range d .Leafs {
1534+ if StripLabel (hash ) == currentBareHash {
1535+ currentLeaf = leaf
1536+ break
1537+ }
1538+ }
1539+
1540+ if currentLeaf == nil {
1541+ continue
1542+ }
1543+
1544+ // Process all children of this leaf
1545+ childHashes := make ([]string , 0 , len (currentLeaf .Links ))
1546+ for _ , childHashWithLabel := range currentLeaf .Links {
1547+ childBareHash := StripLabel (childHashWithLabel )
1548+ childHashes = append (childHashes , childBareHash )
1549+ }
1550+ sort .Strings (childHashes )
1551+
1552+ for _ , childBareHash := range childHashes {
1553+
1554+ // Skip if already visited
1555+ if visited [childBareHash ] {
1556+ continue
1557+ }
1558+ visited [childBareHash ] = true
1559+
1560+ // Assign new label
1561+ newLabel := strconv .Itoa (currentLabel )
1562+ currentLabel ++
1563+
1564+ labelMapping [childBareHash ] = newLabel
1565+
1566+ // Add to queue for processing
1567+ queue = append (queue , childBareHash )
1568+ }
1569+ }
1570+
1571+ newLeafs := make (map [string ]* DagLeaf )
1572+
1573+ for oldHash , leaf := range d .Leafs {
1574+ bareHash := StripLabel (oldHash )
1575+
1576+ // Get the new label for this leaf
1577+ newLabel , exists := labelMapping [bareHash ]
1578+ if ! exists {
1579+ // This leaf wasn't visited (shouldn't happen in a valid DAG)
1580+ continue
1581+ }
1582+
1583+ // Construct new hash
1584+ var newHash string
1585+ if newLabel == "" {
1586+ // Root leaf - no label
1587+ newHash = bareHash
1588+ } else {
1589+ newHash = newLabel + ":" + bareHash
1590+ }
1591+
1592+ // Update the leaf's Hash field
1593+ leaf .Hash = newHash
1594+
1595+ // Update all the links to children with new labels
1596+ if len (leaf .Links ) > 0 {
1597+ newLinks := make (map [string ]string )
1598+ for _ , childHashWithOldLabel := range leaf .Links {
1599+ childBareHash := StripLabel (childHashWithOldLabel )
1600+
1601+ // Get the new label for this child
1602+ childNewLabel , exists := labelMapping [childBareHash ]
1603+ if ! exists {
1604+ // Child wasn't visited (shouldn't happen)
1605+ continue
1606+ }
1607+
1608+ // Construct new child hash
1609+ var newChildHash string
1610+ if childNewLabel == "" {
1611+ // Root as child (shouldn't happen normally)
1612+ newChildHash = childBareHash
1613+ } else {
1614+ newChildHash = childNewLabel + ":" + childBareHash
1615+ }
1616+
1617+ // Add link with new label as key
1618+ newLinks [childNewLabel ] = newChildHash
1619+ }
1620+ leaf .Links = newLinks
1621+ }
1622+
1623+ // Add to new leafs map with new hash as key
1624+ newLeafs [newHash ] = leaf
1625+ }
1626+
1627+ // Replace the leafs map
1628+ d .Leafs = newLeafs
1629+
1630+ // Update root reference if needed
1631+ rootBare := StripLabel (d .Root )
1632+ d .Root = rootBare
1633+
1634+ // Update LatestLabel on root
1635+ if rootLeaf , exists := d .Leafs [d .Root ]; exists {
1636+ rootLeaf .LatestLabel = strconv .Itoa (currentLabel - 1 )
1637+ }
1638+
1639+ return nil
1640+ }
0 commit comments