# shake256-fanout — Makefile.
#
# Builds the reference cuda fan-out worker. Each lumbda tier (Python,
# C, asm) spawns this binary via its existing process-spawn primitive
# & talks to it through input + output portal files. No tier links
# against libcudart directly — the CUDA toolchain dependency stays
# isolated to this directory.
#
# Build:
#   make all       — compile shake256-fanout (needs nvcc)
#   make test      — round-trip test (host + device produce identical
#                    SHAKE256 outputs over a small synthetic input set)
#   make bench     — bench device vs host throughput at N = 100k

NVCC      ?= nvcc
NVCCFLAGS ?= -O3 -arch=sm_86 -Xcompiler="-O3 -Wall -Wextra"
NVCC_PATH ?= $(shell which nvcc 2>/dev/null || echo /usr/local/cuda/bin/nvcc)

all: shake256-fanout cgbn-batch-worker secp256k1-batch-mul

shake256-fanout: shake256-fanout.cu
	$(NVCC) $(NVCCFLAGS) -o $@ $<

# bend form A — secp256k1 batched scalar*G via VanitySearch-Bitcrack
# vendored GPUMath.h (AGPL-3.0). Per-thread Jacobian double-and-add,
# per-thread inversion to affine. See vendor/vanity-search-bitcrack/NOTICE.
NVCCFLAGS_SECP ?= -O3 -arch=sm_86 -Xcompiler="-O3 -Wall"
secp256k1-batch-mul: secp256k1-batch-mul.cu vendor/vanity-search-bitcrack/GPUMath.h
	$(NVCC) $(NVCCFLAGS_SECP) -o $@ $<

secp256k1-test: secp256k1-batch-mul test_secp256k1_known_answers.py
	python3 -u test_secp256k1_known_answers.py ./secp256k1-batch-mul

secp256k1-bench: secp256k1-batch-mul test_secp256k1_known_answers.py
	python3 -u test_secp256k1_known_answers.py ./secp256k1-batch-mul --n 100000

# bend form B — CGBN bignum batch worker.
# CGBN_INC must point at a checkout of https://github.com/NVlabs/CGBN/include
# (header-only consumption; CGBN headers are BSD-3-Clause, our wrapper
# binary stays AGPLv3 — license noted at the top of cgbn-batch-worker.cu).
CGBN_INC ?= $(HOME)/CGBN/include
cgbn-batch-worker: cgbn-batch-worker.cu
	@if [ ! -d "$(CGBN_INC)/cgbn" ]; then \
	  echo "ERROR: CGBN headers not found at $(CGBN_INC)/cgbn"; \
	  echo "  Install: git clone https://github.com/NVlabs/CGBN $(HOME)/CGBN"; \
	  echo "  Or pass: make cgbn-batch-worker CGBN_INC=/path/to/CGBN/include"; \
	  exit 1; \
	fi
	$(NVCC) $(NVCCFLAGS) --extended-lambda -I$(CGBN_INC) -o $@ $<

cgbn-test: cgbn-batch-worker test_cgbn_known_answers.py
	python3 test_cgbn_known_answers.py ./cgbn-batch-worker

# round-trip: feed (cuda-shake-fanout (output-bytes 32) (inputs ...))
# through the binary, compare against an external SHAKE256 reference
# (Python hashlib.shake_256).
test: shake256-fanout test_roundtrip.py
	@printf '(cuda-shake-fanout\n  (output-bytes 32)\n  (inputs\n' > /tmp/cf-in.portal
	@printf '    "00"\n    "01"\n    "deadbeef"\n    "%s"\n' \
		"$$(python3 -c 'print("ab" * 100)')" >> /tmp/cf-in.portal
	@printf '))\n' >> /tmp/cf-in.portal
	./shake256-fanout /tmp/cf-in.portal /tmp/cf-out.portal
	python3 test_roundtrip.py /tmp/cf-in.portal /tmp/cf-out.portal

bench: shake256-fanout bench.py
	python3 bench.py ./shake256-fanout

clean:
	rm -f shake256-fanout /tmp/cf-in.portal /tmp/cf-out.portal
