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.
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
goandmakemanually if not already installed.
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.
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.
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):
discovery- Get familiar with the judge: submit a simple program with no implementation requiredhello- Implement a "Hello, World!" server
Main challenges (build the distributed key-value store):
keyValue- Implement a simple key-value storepersistentKV- Implement a persistent key-value storedistributedKV- Implement a distributed persistent key-value store with replicationconsistentKV- Implement a consistent distributed key-value storequorumKV- Implement a distributed key-value store with quorum-based consistencyknownLeaderKV- Implement a distributed key-value store with a known leaderconsensusKV- Implement a distributed key-value store with a simple consensus protocol
There also some bonus challenges available in the platform for extra points.
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:
-
Instructions - Comments explaining requirements:
// ######################## // ##### INSTRUCTIONS ##### // ########################
-
Helpers - Pre-defined utilities you can use (do not modify):
// ############################ // ###### HELPERS ####### // ###### DO NOT MODIFY ####### // ############################
-
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 }
All make commands must be run from the repository root directory.
- Read the challenge in
challenges/<challenge_name>/README.mdand the challenge file itself - Implement your solution in the TODO sections of the challenge file
- Run unit tests locally to validate:
make test-unit-<challenge_name> # Examples: make test-unit-hello make test-unit-keyValue
- Submit to the judge to get your flag:
make judge-<challenge_name> # Examples: make judge-discovery make judge-hello
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>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
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 commandsFor the full list of available commands and options, run:
makeThis 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