Skip to content

giselerotta/distributed-systems-challenges

 
 

Repository files navigation

Distributed systems challenges

Goal: Solve a series of distributed systems challenges by implementing Go programs that pass the judge's test suite.

For each challenge, you implement specific functionality, validate it locally with unit tests, then submit to the judge which runs a comprehensive test suite. When all tests pass, the judge outputs a CTF flag that you submit on the CTF platform to earn points.

🚀 Local Development Setup

Everything you will need to do will be managed through make commands.

Required Environment: Linux (physical or virtual machine) with go and make installed.

The judge requires Linux. You can run the challenges on:

  • GitHub Codespaces (recommended - comes with all necessary tools pre-installed); see GitHub Codespaces setup guide
  • Linux (native installation or VM) or WSL (Windows Subsystem for Linux) on Windows: Install go and make manually if not already installed.

⚠️ Important: All make commands must be run from the repository root directory. More details on how to run each command are provided in the Testing & Evaluation section below.

🎯 CTF Setup

To participate and earn points, you need to register on the CTF platform and form a team:

📖 See the CTF Platform Guide for detailed step-by-step instructions on registration, team creation, and flag submission.

🎯 Challenge List

The goal is to implement a distributed key-value store that progressively adds features like persistence, replication, consistency, and consensus.

Work your way through in order—each challenge builds on concepts from the previous ones.

Initiation challenges (get familiar with the environment):

  1. discovery - Get familiar with the judge: submit a simple program with no implementation required
  2. hello - Implement a "Hello, World!" server

Main challenges (build the distributed key-value store):

  1. keyValue - Implement a simple key-value store
  2. persistentKV - Implement a persistent key-value store
  3. distributedKV - Implement a distributed persistent key-value store with replication
  4. consistentKV - Implement a consistent distributed key-value store
  5. quorumKV - Implement a distributed key-value store with quorum-based consistency
  6. knownLeaderKV - Implement a distributed key-value store with a known leader
  7. consensusKV - Implement a distributed key-value store with a simple consensus protocol

There also some bonus challenges available in the platform for extra points.

📋 Challenge File Structure

Each challenge is located in challenges/<challenge_name>/challenge/ with:

  • Main challenge file (e.g., keyValue.go)
  • Unit test file (e.g., keyValue_test.go)
  • README with detailed instructions in challenges/<challenge_name>/README.md

Each challenge file has three sections:

  1. Instructions - Comments explaining requirements:

    // ########################
    // ##### INSTRUCTIONS #####
    // ########################
  2. Helpers - Pre-defined utilities you can use (do not modify):

    // ############################
    // ###### 	 HELPERS    #######
    // ###### DO NOT MODIFY #######
    // ############################
  3. Your Code to Complete - Where you write your solution (explicit TODO regions marked with comments):

    // ################################
    // ##### YOU CODE TO COMPLETE #####
    // ################################
    
    func FunctionToComplete() {
       // TODO: implement and return the correct result
    }

⚠️ Important: Only modify code within the designated TODO regions. Altering other parts may cause judge validation to fail.

🧪 Testing & Evaluation

All make commands must be run from the repository root directory.

Step-by-Step Workflow

  1. Read the challenge in challenges/<challenge_name>/README.md and the challenge file itself
  2. Implement your solution in the TODO sections of the challenge file
  3. Run unit tests locally to validate:
    make test-unit-<challenge_name>
    
    # Examples:
    make test-unit-hello
    make test-unit-keyValue
  4. Submit to the judge to get your flag:
    make judge-<challenge_name>
    
    # Examples:
    make judge-discovery
    make judge-hello

Running Unit Tests

Most challenges include unit tests (except discovery). They give a good initial validation before judge submission.

As stated above, run unit tests with:

make test-unit-<challenge_name>

Judge Evaluation & Flag Submission

Once unit tests pass, submit to the judge:

How it works:

  • The judge runs several instances of your program simultaneously on different ports
  • Each instance is aware of other instances' ports (in most challenges), allowing inter-process communication
  • The judge captures all output in log files: process_<port>.log

Success: When all tests pass, the judge outputs a flag: CTF{...}
Submit this flag on the CTF platform to earn points.

Debugging: If judge evaluation fails:

  • Check the log files (process_<port>.log) to see what went wrong
  • Add sufficient logging to your implementation to help debug issues
  • The judge is a black-box validator; use challenge requirements as your guide

Appendix: Available Make Commands

Quick reference for the most common commands:

make test-unit-<challenge>     # Run unit tests for a challenge
make judge-<challenge>         # Submit to challenge to the judge
make                           # Show all available commands

For the full list of available commands and options, run:

make

This prints out the following help message:

Available Makefile targets:

  make clean                              Remove build artifacts
  make verify-challenges                  Check all challenges are available

Test challenges locally (unit tests):
  make test-unit-<challenge>              Run unit tests for a challenge
  make unit-test-all                      Run unit tests for all challenges

  Examples: make test-unit-hello, make test-unit-keyValue

Evaluate with judge:
  make judge-<challenge>                  Evaluate a challenge with the judge

  Optional arguments:
    NUM_INSTANCES=<n>    Number of instances to launch (default: 10)
    START_PORT=<port>    Starting port number (default: 3000)

  Examples: make judge-hello, make judge-keyValue NUM_INSTANCES=5 START_PORT=5000

Available challenges:
  discovery, hello, keyValue, persistentKV, distributedKV,
  consistentKV, quorumKV, knownLeaderKV, consensusKV

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Go 89.7%
  • Makefile 10.3%