Fundamentals of Distributed Algorithms