code: func (f *fragment) Blocks() []FragmentBlock {
  	f.mu.Lock()
  	defer f.mu.Unlock()
  
  	var a []FragmentBlock
  
  	// Initialize the iterator.
  	itr := f.storage.Iterator()
  	itr.Seek(0)
  
  	// Initialize block hasher.
  	h := newBlockHasher()
  
  	// Iterate over each value in the fragment.
  	v, eof := itr.Next()
  	if eof {
  		return nil
  	}
  	blockID := int(v / (HashBlockSize * ShardWidth))
  	for {
  		// Check for multiple block checksums in a row.
  		if n := f.readContiguousChecksums(&a, blockID); n > 0 {
  			itr.Seek(uint64(blockID+n) * HashBlockSize * ShardWidth)
  			v, eof = itr.Next()
  			if eof {
  				break
  			}
  			blockID = int(v / (HashBlockSize * ShardWidth))
  			continue
  		}
  
  		// Reset hasher.
  		h.blockID = blockID
  		h.Reset()
  
  		// Read all values for the block.
  		for ; ; v, eof = itr.Next() {
  			// Once we hit the next block, save the value for the next iteration.
  			blockID = int(v / (HashBlockSize * ShardWidth))
  			if blockID != h.blockID || eof {
  				break
  			}
  
  			h.WriteValue(v)
  		}
  
  		// Cache checksum.
  		chksum := h.Sum()
  		f.checksums[h.blockID] = chksum
  
  		// Append block.
  		a = append(a, FragmentBlock{
  			ID:       h.blockID,
  			Checksum: chksum,
  		})
  
  		// Exit if we're at the end.
  		if eof {
  			break
  		}
  	}
  
  	return a
  }
docs: // Blocks returns info for all blocks containing data.