.POSIX: # Suppress all directory-related messages for cleaner output MAKEFLAGS += --no-print-directory # Install prefix PREFIX = $(HOME)/.cargo # Cargo binary CARGO = cargo # Compile target RUST_TARGET = $(shell rustc -Vv | grep '^host: ' | cut -d' ' -f2) # Uncomment when doing musl static builds #RUSTFLAGS = -C target-feature=+crt-static -C link-self-contained=yes # Root directory of the project PROJECT_ROOT = ../../.. # Directory where logs are stored LOG_HOME := $(shell echo ~/.local/share/darkfi/logs) # This is the main binary built by the Makefile. # Its corresponding configuration file is used to start the node. EXPLORERD_BIN := $(shell grep '^name = ' Cargo.toml | sed 1q | cut -d' ' -f3 | tr -d '"') EXPLORERD_CONFIG := $(EXPLORERD_BIN)_config.toml # If these binaries are missing when launching the explorer node environment, # the Makefile (via a sub-make call) will build them if needed. Their configurations # are used to start the nodes. DARKFID_BIN := $(PROJECT_ROOT)/darkfid DARKFID_CONFIG := $(PROJECT_ROOT)/bin/darkfid/darkfid_config.toml # Source to build SRC = \ Cargo.toml \ $(PROJECT_ROOT)/Cargo.toml \ $(shell find src -type f -name '*.rs') \ $(shell find $(PROJECT_ROOT)/src -type f -name '*.rs') \ all: $(EXPLORERD_BIN) help: @echo "Explorerd Makefile Commands:" @echo "" @echo "Build targets:" @echo " make - Build the $(EXPLORERD_BIN) binary" @echo " make clean - Remove build artifacts" @echo " make install - Install $(EXPLORERD_BIN) to $(PREFIX)/bin" @echo " make uninstall - Remove $(EXPLORERD_BIN) from $(PREFIX)/bin" @echo "" @echo "Network management:" @echo " make start-localnet - Start the explorer node environment on localnet" @echo " make start-testnet - Start the explorer node environment on testnet" @echo " make start-mainnet - Start the explorer node environment on mainnet" @echo " ** Use VERBOSE=-vv or -vvv for debugging (applies to start-% commands only)" @echo "" @echo " make stop - Stop all nodes running within the explorer node environment" @echo "" @echo "Utility targets:" @echo " make bundle_contracts_src - Bundle contract sources and ZK proofs into tar archives in native_contracts_src directory" @echo " make await-startup-{network} - Wait until nodes are ready (used in scripting, replace {network} with localnet/testnet/mainnet)" @echo "" @echo "Log files are stored in: $(LOG_HOME)/{localnet|testnet|mainnet}/" $(EXPLORERD_BIN): $(SRC) bundle_contracts_src RUSTFLAGS="$(RUSTFLAGS)" $(CARGO) build --target=$(RUST_TARGET) --release --package $@ cp -f $(PROJECT_ROOT)/target/$(RUST_TARGET)/release/$@ $@ cp -f $(PROJECT_ROOT)/target/$(RUST_TARGET)/release/$@ $(PROJECT_ROOT)/$@ clean: RUSTFLAGS="$(RUSTFLAGS)" $(CARGO) clean --target=$(RUST_TARGET) --release --package $(EXPLORERD_BIN) rm -f $(EXPLORERD_BIN) $(PROJECT_ROOT)/$(EXPLORERD_BIN) rm -rf native_contracts_src install: all mkdir -p $(DESTDIR)$(PREFIX)/bin cp -f $(EXPLORERD_BIN) $(DESTDIR)$(PREFIX)/bin chmod 755 $(DESTDIR)$(PREFIX)/bin/$(EXPLORERD_BIN) uninstall: rm -f $(DESTDIR)$(PREFIX)/bin/$(EXPLORERD_BIN) # Bundles contract sources and ZK proofs into tar archives, supporting both GNU and BSD tar bundle_contracts_src: @TMP_DIR="native_contracts_src/tmp"; \ CONTRACT_SRC_DIR="$(PROJECT_ROOT)/src/contract"; \ CONTRACTS="deployooor money dao"; \ set -e; \ # Create a temporary directory and clean up on exit \ mkdir -p "$$TMP_DIR"; \ trap "rm -rf $$TMP_DIR" 0 1 2 15; \ # Bundle each native contract \ for contract in $$CONTRACTS; do \ PROOF_DIR="$$TMP_DIR/$$contract/proof"; \ mkdir -p "$$TMP_DIR/$$contract"; \ cp -R "$$CONTRACT_SRC_DIR/$$contract/src/"* "$$TMP_DIR/$$contract"; \ # Include zk proofs if they exist \ if [ -d "$$CONTRACT_SRC_DIR/$$contract/proof" ]; then \ mkdir -p "$$PROOF_DIR"; \ find "$$CONTRACT_SRC_DIR/$$contract/proof" -type f ! -name '*.bin' -exec cp {} "$$PROOF_DIR/" \; ; \ # Move witness files to their own directory if present \ if find "$$PROOF_DIR" -name '*.json' | grep -q .; then \ mkdir -p "$$PROOF_DIR/witness"; \ mv "$$PROOF_DIR"/*.json "$$PROOF_DIR/witness"; \ fi; \ fi; \ (cd "$$TMP_DIR/$$contract" && tar --format=pax -cf ../../$${contract}_contract_src.tar *); \ done; # Starts an explorer node environment for `localnet`, `testnet`, or `mainnet` networks. # It validates the input network, stops any currently running nodes, initializes the log directory, # and starts the remaining nodes while waiting for them to properly initialize. start-%: check-darkfid check-explorerd @if [ "$*" != "localnet" ] && [ "$*" != "testnet" ] && [ "$*" != "mainnet" ]; then \ echo "Error: Unsupported network '$*'. Use 'localnet', 'testnet', or 'mainnet'."; \ exit 1; \ fi @$(MAKE) stop suppress_not_running=1 @echo "Starting explorer node environment $*..." @sh -c ' \ LOG_DIR=$(LOG_HOME)/$*; \ mkdir -p "$$LOG_DIR"; \ $(DARKFID_BIN) $(VERBOSE) --log "$$LOG_DIR/darkfid.log" -c $(DARKFID_CONFIG) --network $* & echo $$! >> PIDs.txt; sleep 2; \ $(call wait_for_darkfid_startup, $$LOG_DIR) \ ./$(EXPLORERD_BIN) $(VERBOSE) --log "$$LOG_DIR/explorerd.log" -c $(EXPLORERD_CONFIG) --network $* & echo $$! >> PIDs.txt; \ $(call wait_for_explorerd_startup, $$LOG_DIR) \ ' # Starts an explorer node in no-sync mode for `localnet`, `testnet`, or `mainnet` networks. # In no-sync mode, no connections are made with the Darkfi blockchain network and the explorer # relies solely on a local database without attempting synchronization. As with the `start-%` # target, inputs are verified, any running nodes are stopped, the log directory is initialized, # and the node is started. start-no-sync-%: check-contracts check-explorerd @if [ "$*" != "localnet" ] && [ "$*" != "testnet" ] && [ "$*" != "mainnet" ]; then \ echo "Error: Unsupported network '$*'. Use 'localnet', 'testnet', or 'mainnet'."; \ exit 1; \ fi @$(MAKE) stop suppress_not_running=1 @echo "Starting explorer node environment (no sync) $*..." @sh -c ' \ LOG_DIR=$(LOG_HOME)/$*; \ mkdir -p "$$LOG_DIR"; \ ./$(EXPLORERD_BIN) --log "$$LOG_DIR/explorerd.log" -c $(EXPLORERD_CONFIG) --network $* --no-sync & echo $$! >> PIDs.txt; \ $(call wait_for_explorerd_startup, $$LOG_DIR) \ ' # Check and build darkfid if it does not exist check-darkfid: @if [ ! -f "$(DARKFID_BIN)" ]; then \ echo "Building darkfid..."; \ $(MAKE) -C "$(PROJECT_ROOT)" darkfid; \ fi # Check and build explorerd if it does not exist check-explorerd: @if [ ! -f "$(EXPLORERD_BIN)" ]; then \ echo "Building explorerd..."; \ $(MAKE) -C .; \ fi # Check and build contracts if they do not exist check-contracts: @if [ ! -f "$(PROJECT_ROOT)/src/contract/money/darkfi_money_contract.wasm" ] \ || [ ! -f "$(PROJECT_ROOT)/contract/dao/darkfi_dao_contract.wasm" ] \ || [ ! -f "$(PROJECT_ROOT)/contract/deployooor/darkfi_deployooor_contract.wasm" ]; then \ echo "Building contracts..."; \ $(MAKE) -C "$(PROJECT_ROOT)" contracts; \ fi # Stop the running network # Usage: make stop [suppress_not_running=1] stop: @if [ -f PIDs.txt ]; then \ while read PID; do \ if ps -p $$PID > /dev/null 2>&1; then \ kill -15 $$PID 2>/dev/null; \ sleep 5; \ ps -p $$PID > /dev/null 2>&1 && kill -9 $$PID 2>/dev/null; \ fi; \ done < PIDs.txt; \ rm -f PIDs.txt; \ echo "Stopped explorer node environment"; \ else \ if [ "$(suppress_not_running)" != "1" ]; then \ echo "Explorer node environment not running, nothing to stop."; \ fi; \ fi # Wait for the network to start await-startup-%: @$(call wait_for_darkfid_startup,$(LOG_HOME)/$*) @$(call wait_for_explorerd_startup,$(LOG_HOME)/$*) # Wait for the explorer node environment to start in no-sync mode (skip waiting for darkfid startup) await-startup-no-sync-%: @$(call wait_for_explorerd_startup,$(LOG_HOME)/$*) # Waits for Darkfid to start define wait_for_darkfid_startup log_dir=$(strip $(1)); \ while ! grep -q "Blockchain synced!" "$$log_dir/darkfid.log" 2>/dev/null; do \ sleep 1; \ done; endef # Waits for Explorerd to start define wait_for_explorerd_startup log_dir=$(strip $(1)); \ while ! grep -q "Started DarkFi Explorer Node" "$$log_dir/explorerd.log" 2>/dev/null; do \ sleep 1; \ done; endef .PHONY: help all clean install uninstall bundle_contracts_src check-darkfid check-explorerd stop start-%