ORLY relay uses pure Go builds (`CGO_ENABLED=0`) across all platforms. The p8k cryptographic library uses purego to dynamically load libsecp256k1 at runtime, eliminating the need for CGO during compilation.
libsecp256k1 (fallback to pure Go p256k1)go build works everywhereThe p8k library (from git.mleku.dev/mleku/nostr) uses purego to:
CGO_ENABLED=0)libsecp256k1- If library found → use fast C implementation - If library not found → automatically fallback to pure Go p256k1
The library can be downloaded from: https://git.nostrdev.com/mleku/nostr/raw/branch/main/crypto/p8k/libsecp256k1.so
Platform-specific search locations:
Linux:
./libsecp256k1.so (current directory)/usr/lib/libsecp256k1.so.2/usr/local/lib/libsecp256k1.so.2/lib/libsecp256k1.so.2macOS:
./libsecp256k1.dylib (current directory)/usr/local/lib/libsecp256k1.dylib/opt/homebrew/lib/libsecp256k1.dylibWindows:
libsecp256k1.dll (current directory)# Just works - no CGO needed
go build .
# Build for all platforms
./scripts/build-all-platforms.sh
# Outputs to build/ directory:
# - orly-v0.25.0-linux-amd64
# - orly-v0.25.0-linux-arm64
# - orly-v0.25.0-darwin-amd64
# - orly-v0.25.0-darwin-arm64
# - orly-v0.25.0-windows-amd64.exe
# - libsecp256k1-linux-amd64.so (optional)
# From Linux, build for macOS
GOOS=darwin GOARCH=arm64 CGO_ENABLED=0 go build -o orly-macos .
# From macOS, build for Windows
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -o orly.exe .
# From any platform, build for any platform
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o orly-arm64 .
When libsecp256k1 is available at runtime:
When library is not found, automatic fallback to pure Go:
Distribute just the binary:
# Just copy and run
scp orly-v0.25.0-linux-amd64 server:~/orly
ssh server "./orly"
Distribute binary with library:
# Copy both
scp orly-v0.25.0-linux-amd64 server:~/orly
scp libsecp256k1-linux-amd64.so server:~/libsecp256k1.so
ssh server "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH && ./orly"
Install library system-wide:
# On Ubuntu/Debian
sudo apt-get install libsecp256k1-1
# Binary automatically finds it
./orly
All build and test scripts now use CGO_ENABLED=0:
scripts/build-all-platforms.sh - Multi-platform buildsscripts/deploy.sh - Production deploymentscripts/benchmark.sh - Benchmark buildscmd/benchmark/profile.sh - Profiling buildsscripts/test.sh - Main test runnerscripts/runtests.sh - Comprehensive testsscripts/test_policy.sh - Policy testsscripts/test-managed-acl.sh - ACL testsscripts/test-workflow-local.sh - CI/CD simulationscripts/test-deploy-local.sh - Deployment tests.github/workflows/go.yml - GitHub Actionscmd/benchmark/Dockerfile.next-orly - Docker buildscmd/benchmark/Dockerfile.benchmark - Benchmark container| Platform | CGO | Cross-Compile | Library Runtime | Status |
|---|---|---|---|---|
| Linux AMD64 | ✗ | ✓ Native | ✓ Optional | ✓ Full |
| Linux ARM64 | ✗ | ✓ Pure Go | ✓ Optional | ✓ Full |
| macOS AMD64 | ✗ | ✓ Pure Go | ✓ Optional | ✓ Full |
| macOS ARM64 | ✗ | ✓ Pure Go | ✓ Optional | ✓ Full |
| Windows AMD64 | ✗ | ✓ Pure Go | ✓ Optional | ✓ Full |
| Android ARM64 | ✗ | ✓ Pure Go | ✓ Optional | ✓ Full |
| Android AMD64 | ✗ | ✓ Pure Go | ✓ Optional | ✓ Full |
All platforms: Pure Go build, runtime library optional
Previously, the project used CGO builds:
Now with purego:
| Build Type | Time | Notes |
|---|---|---|
| CGO (old) | ~45s | With C compilation |
| Purego (new) | ~15s | Pure Go only |
3x faster builds with purego
| Build Type | Size | Notes |
|---|---|---|
| CGO (old) | ~28 MB | Statically linked |
| Purego (new) | ~32 MB | Pure Go with purego |
Slightly larger but no C dependencies
| Operation | CGO (old) | Purego + lib | Purego fallback |
|---|---|---|---|
| Schnorr Sign | 15K/s | 15K/s | 5K/s |
| Schnorr Verify | 6K/s | 6K/s | 2K/s |
| ECDH | 12K/s | 12K/s | 4K/s |
Same performance with library, acceptable fallback
# Complex setup
sudo apt-get install gcc autoconf automake libtool
git clone https://github.com/bitcoin-core/secp256k1.git
cd secp256k1 && ./autogen.sh && ./configure && make && sudo make install
# Cross-compilation nightmares
sudo apt-get install gcc-aarch64-linux-gnu gcc-mingw-w64-x86-64
export CC=aarch64-linux-gnu-gcc
CGO_ENABLED=1 GOOS=linux GOARCH=arm64 go build . # Often fails
# Just works
go build .
# Cross-compilation just works
GOOS=linux GOARCH=arm64 go build .
GOOS=windows GOARCH=amd64 go build .
GOOS=darwin GOARCH=arm64 go build .
All tests work with CGO_ENABLED=0:
# Run all tests
./scripts/test.sh
# Tests automatically detect library
# - With library: tests use C implementation
# - Without library: tests use pure Go fallback
Dockerfiles simplified:
# No more build dependencies
FROM golang:1.25-alpine AS builder
WORKDIR /build
COPY . .
RUN CGO_ENABLED=0 go build -ldflags "-s -w" -o orly .
# Runtime includes libsecp256k1.so from repository
FROM alpine:latest
RUN apk add --no-cache ca-certificates
COPY --from=builder /build/orly /app/orly
COPY --from=builder /build/libsecp256k1.so /app/libsecp256k1.so
ENV LD_LIBRARY_PATH=/app
CMD ["/app/orly"]
These are normal and expected:
p8k: failed to load libsecp256k1: no such file
p8k: using pure Go fallback implementation
This is fine - the fallback works correctly.
To verify library is being used:
# Linux
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
./orly
# macOS
export DYLD_LIBRARY_PATH=.:$DYLD_LIBRARY_PATH
./orly
# Windows
# Place libsecp256k1.dll in same directory as .exe
The p8k library logs its status:
p8k: libsecp256k1 loaded successfully
p8k: schnorr module available
p8k: ecdh module available
The purego build system provides:
All platforms can use purego - it's enabled everywhere by default.