Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 52 additions & 31 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,32 @@
# List of binaries hacknet needs to function properly
COMMANDS := sudo tar zstd getent stress
# OS Detection and Cross-Platform Support
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
OS := macos
export UID := $(shell id -u)
export GID := $(shell id -g)
# macOS: use sysctl for CPU count
STRESS_CORES ?= $(shell sysctl -n hw.ncpu)
# List of binaries hacknet needs to function properly
COMMANDS := sudo tar zstd stress
TAR_EXTRACT_FLAGS := -xf
else
OS := linux
# Linux: use getent
export UID := $(shell getent passwd $$(whoami) | cut -d":" -f 3)
export GID := $(shell getent passwd $$(whoami) | cut -d":" -f 4)
# Linux: use /proc/cpuinfo for CPU count
STRESS_CORES ?= $(shell cat /proc/cpuinfo | grep processor | wc -l)
# List of binaries hacknet needs to function properly
COMMANDS := sudo tar zstd getent stress
TAR_EXTRACT_FLAGS := --same-owner -xf
endif

# Verify required dependencies exist
$(foreach bin,$(COMMANDS),\
$(if $(shell command -v $(bin) 2> /dev/null),$(info),$(error Missing required dependency: `$(bin)`)))
TARGET := $(firstword $(MAKECMDGOALS))
PARAMS := $(filter-out $(TARGET),$(MAKECMDGOALS))

# Hardcode the chainstate dir if we're booting from genesis
ifeq ($(TARGET),up-genesis)
export CHAINSTATE_DIR := $(PWD)/docker/chainstate/genesis
Expand All @@ -12,9 +35,6 @@ ifeq ($(TARGET),genesis)
export CHAINSTATE_DIR := $(PWD)/docker/chainstate/genesis
endif

# UID and GID are not currently used, but may be later to ensure consistent file permissions
export UID := $(shell getent passwd $$(whoami) | cut -d":" -f 3)
export GID := $(shell getent passwd $$(whoami) | cut -d":" -f 4)
EPOCH := $(shell date +%s)
PWD = $(shell pwd)
# Set a unique project name (used for checking if the network is running)
Expand All @@ -26,22 +46,21 @@ SERVICES := $(shell CHAINSTATE_DIR="" docker compose -f docker/docker-compose.ym
# Pauses the bitcoin miner script. Default is set to nearly 1 trillion blocks
PAUSE_HEIGHT ?= 999999999999
# Used for the stress testing target. modifies how much cpu to consume for how long
STRESS_CORES ?= $(shell cat /proc/cpuinfo | grep processor | wc -l)
STRESS_TIMEOUT ?= 120

# Create the chainstate dir and extract an archive to it when the "up" target is used
$(CHAINSTATE_DIR): /usr/bin/tar /usr/bin/zstd
@if [ ! -d "$(CHAINSTATE_DIR)" ]; then \
mkdir -p $(CHAINSTATE_DIR)
@if [ "$(TARGET)" = "up" ]; then
if [ -f "$(CHAINSTATE_ARCHIVE)" ]; then
sudo tar --same-owner -xf $(CHAINSTATE_ARCHIVE) -C $(CHAINSTATE_DIR) || exit 1
else
@echo "Chainstate archive ($(CHAINSTATE_ARCHIVE)) not found. Exiting"
rm -rf $(CHAINSTATE_DIR)
exit 1
fi
fi
$(CHAINSTATE_DIR):
@if [ ! -d "$(CHAINSTATE_DIR)" ]; then \
mkdir -p $(CHAINSTATE_DIR); \
if [ "$(TARGET)" = "up" ]; then \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we re-add @ and remove all the nested \s? It's visually better.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the backslashes manually because they make the intent explicit by defining how multi-line commands are interpreted. I've followed the documented convention https://www.gnu.org/software/make/manual/html_node/Splitting-Recipe-Lines.html

The previous implementation was functioning correctly, so we can keep it as it was if you prefer.

if [ -f "$(CHAINSTATE_ARCHIVE)" ]; then \
sudo tar $(TAR_EXTRACT_FLAGS) $(CHAINSTATE_ARCHIVE) -C $(CHAINSTATE_DIR) || exit 1; \
else \
echo "Chainstate archive ($(CHAINSTATE_ARCHIVE)) not found. Exiting"; \
rm -rf $(CHAINSTATE_DIR); \
exit 1; \
fi; \
fi; \
fi

# Build the images with a cache if present
Expand Down Expand Up @@ -75,7 +94,7 @@ check-running:
exit 1; \
fi

# For targets that need an arg, check that *something* is provided. it not, exit
# For targets that need an arg, check that *something* is provided. if not, exit
check-params: | check-running
@if [ ! "$(PARAMS)" ]; then \
echo "No service defined. Exiting"; \
Expand All @@ -85,15 +104,17 @@ check-params: | check-running
# Boot the network from a local chainstate archive
up: check-not-running | build $(CHAINSTATE_DIR)
@echo "Starting $(PROJECT) network from chainstate archive"
@echo " OS: $(OS)"
@echo " Chainstate Dir: $(CHAINSTATE_DIR)"
@echo " Chainstate Archive: $(CHAINSTATE_ARCHIVE)"
echo "$(CHAINSTATE_DIR)" > .current-chainstate-dir
docker compose -f docker/docker-compose.yml --profile default -p $(PROJECT) up -d

# Boot the network from genesis
genesis: check-not-running | build $(CHAINSTATE_DIR) /usr/bin/sudo
genesis: check-not-running | build $(CHAINSTATE_DIR)
@echo "Starting $(PROJECT) network from genesis"
@if [ -d "$(CHAINSTATE_DIR)" ]; then \
@echo " OS: $(OS)"
@if [ -d "$(CHAINSTATE_DIR)" ]; then \
echo " Removing existing genesis chainstate dir: $(CHAINSTATE_DIR)"; \
sudo rm -rf $(CHAINSTATE_DIR); \
fi
Expand All @@ -118,7 +139,7 @@ down: backup-logs current-chainstate-dir
@echo "Shutting down $(PROJECT) network"
docker compose -f docker/docker-compose.yml --profile default -p $(PROJECT) down
@if [ -f .current-chainstate-dir ]; then \
rm -f .current-chainstate-dir
rm -f .current-chainstate-dir; \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this addition needed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

technically no, since it's the end of the conditional

fi

# Secondary name to bring down the genesis network
Expand All @@ -129,7 +150,7 @@ down-force:
@echo "Force Shutting down $(PROJECT) network"
docker compose -f docker/docker-compose.yml --profile default -p $(PROJECT) down
@if [ -f .current-chainstate-dir ]; then \
rm -f .current-chainstate-dir
rm -f .current-chainstate-dir; \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here regarding \.

Copy link
Contributor

@BowTiedRadone BowTiedRadone Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess all these side changes were created by a formatter. I'm curious what's the formatter, maybe we can take it into account for our CI. We're currently using dclint for docker-compose related files, but one for Makefile would be a great idea.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makefile linter would be great! i think it would be challenging since we use a "shell-ified" makefile though

fi

# Stream specified service logs to STDOUT. Does not validate if PARAMS is supplied
Expand All @@ -142,15 +163,15 @@ log-all: current-chainstate-dir
docker compose -f docker/docker-compose.yml --profile default -p $(PROJECT) logs -t -f

# Backup all service logs to $ACTIVE_CHAINSTATE_DIR/logs/<service-name>.log
backup-logs: current-chainstate-dir /usr/bin/sudo
backup-logs: current-chainstate-dir
@if [ -f .current-chainstate-dir ]; then \
$(eval ACTIVE_CHAINSTATE_DIR=$(shell cat .current-chainstate-dir))
if [ ! -d "$(ACTIVE_CHAINSTATE_DIR)" ]; then \
echo "Chainstate Dir ($(ACTIVE_CHAINSTATE_DIR)) not found";\
$(eval ACTIVE_CHAINSTATE_DIR=$(shell cat .current-chainstate-dir)) \
if [ ! -d "$(ACTIVE_CHAINSTATE_DIR)" ]; then \
echo "Chainstate Dir ($(ACTIVE_CHAINSTATE_DIR)) not found"; \
exit 1; \
fi; \
if [ ! -d "$(ACTIVE_CHAINSTATE_DIR)/logs" ]; then \
mkdir -p $(ACTIVE_CHAINSTATE_DIR)/logs;\
if [ ! -d "$(ACTIVE_CHAINSTATE_DIR)/logs" ]; then \
mkdir -p $(ACTIVE_CHAINSTATE_DIR)/logs; \
fi; \
echo "Backing up logs to $(ACTIVE_CHAINSTATE_DIR)/logs"; \
for service in $(SERVICES); do \
Expand All @@ -161,7 +182,7 @@ backup-logs: current-chainstate-dir /usr/bin/sudo
# Replace the existing chainstate archive. Will be used with target `up`
snapshot: current-chainstate-dir down
@echo "Creating $(PROJECT) chainstate snapshot from $(ACTIVE_CHAINSTATE_DIR)"
@if [ -d "$(ACTIVE_CHAINSTATE_DIR)/logs" ]; then \
@if [ -d "$(ACTIVE_CHAINSTATE_DIR)/logs" ]; then \
rm -rf $(ACTIVE_CHAINSTATE_DIR)/logs; \
fi
@echo "Creating snapshot: $(CHAINSTATE_ARCHIVE)"
Expand Down Expand Up @@ -220,5 +241,5 @@ monitor:
clean: down-force
sudo rm -rf ./docker/chainstate/*

.PHONY: build build-no-cache current-chainstate-dir check-not-running check-running check-params up genesis up-genesis down down-genesis down-force log log-all backup-logs snapshot pause unpause stop start restart stress test monitor clean
.PHONY: build build-no-cache current-chainstate-dir check-not-running check-running check-params up genesis up-genesis down down-genesis down-force log log-all backup-logs snapshot pause unpause stop start restart stress test monitor clean up-prom down-prom
.ONESHELL: all-in-one-shell
4 changes: 2 additions & 2 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ x-common-vars:
- &STACKS_20_HEIGHT ${STACKS_20_HEIGHT:-0}
- &STACKS_2_05_HEIGHT ${STACKS_2_05_HEIGHT:-203}
- &STACKS_21_HEIGHT ${STACKS_21_HEIGHT:-204}
- &STACKS_POX2_HEIGHT ${STACKS_POX2_HEIGHT:-205} # 104 is is stacks_block=1, 106 is stacks_block=3
- &STACKS_POX2_HEIGHT ${STACKS_POX2_HEIGHT:-205} # 104 is stacks_block=1, 106 is stacks_block=3
- &STACKS_22_HEIGHT ${STACKS_22_HEIGHT:-206}
- &STACKS_23_HEIGHT ${STACKS_23_HEIGHT:-207}
- &STACKS_24_HEIGHT ${STACKS_24_HEIGHT:-208}
Expand All @@ -86,7 +86,7 @@ x-common-vars:
- &REWARD_RECIPIENT_1 ${REWARD_RECIPIENT_1:-ST1XVSVQN0KP5SDYFNT8E5TXWVW0XZVQEDBMCJ3XM} # priv: a6143d20cd73d0dce2179e2af7771372a95b9d6795924492bd4d15d17709531e01
- &REWARD_RECIPIENT_2 ${REWARD_RECIPIENT_2:-ST2FW15NGB4H76FMVXKHYYSM865YVS6V3SA1GNABC} # priv: fe3087801196d8027008146b13e6d365920c2e4b7bc9969729ec2f0f22ef74fc01
- &REWARD_RECIPIENT_3 ${REWARD_RECIPIENT_3:-ST2MES40ZEXTX9M4YXW9QSWHRVC9HYT419S198VPM} # priv: ed7eb063c61b8e892987228f1fcfb74eab5009568861613dc4b074b708a7893701
- &STACKS_CORE_BASE_BRANCH ${STACKS_CORE_BASE_BRANCH:-3.3.0.0.1}
- &STACKS_CORE_BASE_BRANCH ${STACKS_CORE_BASE_BRANCH:-7ff75a23439879a1316b1423587bfd0dac17a44f} # branch, tag, or commit SHA
- &PAUSE_HEIGHT ${PAUSE_HEIGHT:-999999999999}
- &PAUSE_TIMER 86400000

Expand Down
18 changes: 14 additions & 4 deletions docker/stacks/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
FROM rust:bookworm AS builder

# This will be overridden by the value from docker-compose
# Supports: branch name, tag, or commit SHA
# Examples:
# STACKS_CORE_BASE_BRANCH=develop (branch)
# STACKS_CORE_BASE_BRANCH=3.3.0.0.1 (tag)
# STACKS_CORE_BASE_BRANCH=abc123def456 (commit)
ARG STACKS_CORE_BASE_BRANCH=master

RUN echo "Building Stacks Core from branch: $STACKS_CORE_BASE_BRANCH"
RUN echo "Building Stacks Core from: $STACKS_CORE_BASE_BRANCH"

# Clone efficiently: shallow for branches/tags, targeted fetch for commits
RUN git init /code/stacks-core && \
cd /code/stacks-core && \
git remote add origin https://github.com/stacks-network/stacks-core.git && \
git fetch --depth=1 origin $STACKS_CORE_BASE_BRANCH && \
git checkout FETCH_HEAD

# Clone the specified branch from GitHub
RUN git clone --branch $STACKS_CORE_BASE_BRANCH --single-branch --depth=1 https://github.com/stacks-network/stacks-core.git /code/stacks-core
WORKDIR /code/stacks-core
RUN apt-get update && apt-get install -y git libclang-dev llvm
RUN apt-get update && apt-get install -y libclang-dev llvm

# Run an build that we'll cache the result of and then build the code
RUN cargo build --features monitoring_prom,slog_json --bin stacks-node --bin stacks-signer
Expand Down