Skip to content
Merged
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
15 changes: 11 additions & 4 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,23 @@
.github
.gitignore
.dockerignore
Dockerfile
README.md
bench
docs
img
tests

# Makefile artifacts
# The image is built from the repository root, so that the Makefile, src/ and
# kernels/ are in the context. The Dockerfile itself is not needed inside it,
# but docker/entrypoint.sh is, so the directory cannot be excluded wholesale.
docker/Dockerfile

# Makefile artifacts, the image runs its own build
build
bin
*.o
*.so
*.x64
*.exe
cache-opencl.*
bin
__pycache__/
.venv
2 changes: 2 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ jobs:
uses: docker/build-push-action@v6
with:
context: .
file: docker/Dockerfile
load: true
tags: profanity2:ci
cache-from: type=gha
Expand Down Expand Up @@ -65,6 +66,7 @@ jobs:
uses: docker/build-push-action@v6
with:
context: .
file: docker/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Makefile artifacts
build/
bin/
*.o
*.so
*.x64
*.exe
cache-opencl.*
bin
__pycache__/
.venv
50 changes: 39 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
CC=g++
CDEFINES=
SOURCES=Dispatcher.cpp Mode.cpp precomp.cpp profanity.cpp SpeedSample.cpp
OBJECTS=$(SOURCES:.cpp=.o)

SRCDIR=src
KERNELDIR=kernels
OBJDIR=build
BINDIR=bin

SOURCES=$(addprefix $(SRCDIR)/,Dispatcher.cpp Mode.cpp precomp.cpp profanity.cpp SpeedSample.cpp)
OBJECTS=$(patsubst $(SRCDIR)/%.cpp,$(OBJDIR)/%.o,$(SOURCES))

# The kernels are copied next to the binary because that is the first place
# profanity2 looks for them, which makes bin/ self-contained: it can be copied
# elsewhere and run from any working directory.
KERNELS=$(addprefix $(BINDIR)/,keccak.cl profanity.cl)

# On Windows the OS environment variable is always set to Windows_NT.
# Checking it first avoids calling `uname`, which is unavailable outside
# of MSYS2/Cygwin shells (e.g. when using mingw32-make from cmd.exe).
ifeq ($(OS),Windows_NT)
EXECUTABLE=profanity2.exe
EXECUTABLE=$(BINDIR)/profanity2.exe
# -mcmodel=large is not reliably supported by MinGW GCC on Windows
# targets, and htonl/ntohl live in ws2_32 there.
# -static bundles the MinGW runtimes (libstdc++, libgcc, winpthread) so
Expand All @@ -17,14 +28,22 @@ ifeq ($(OS),Windows_NT)
LDFLAGS=-s -static -l:libOpenCL.dll.a -lws2_32
CFLAGS=-c -std=c++11 -Wall -mmmx -O2
# MSYSTEM is set inside MSYS2 shells, where unix commands are available.
# Outside of them the recipes have to speak cmd.exe, which wants
# backslashes and refuses to mkdir a directory that already exists.
ifdef MSYSTEM
RM=rm -f
MKDIR=mkdir -p $1
COPY=cp -f $1 $2
RMDIR=rm -rf $1
else
RM=del /Q
MKDIR=if not exist "$(subst /,\,$1)" mkdir "$(subst /,\,$1)"
COPY=copy /Y "$(subst /,\,$1)" "$(subst /,\,$2)" >NUL
RMDIR=if exist "$(subst /,\,$1)" rmdir /S /Q "$(subst /,\,$1)"
endif
else
EXECUTABLE=profanity2.x64
RM=rm -f
EXECUTABLE=$(BINDIR)/profanity2.x64
MKDIR=mkdir -p $1
COPY=cp -f $1 $2
RMDIR=rm -rf $1
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
LDFLAGS=-framework OpenCL
Expand All @@ -35,13 +54,22 @@ else
endif
endif

all: $(SOURCES) $(EXECUTABLE)
.PHONY: all clean

$(EXECUTABLE): $(OBJECTS)
all: $(EXECUTABLE) $(KERNELS)

$(EXECUTABLE): $(OBJECTS) | $(BINDIR)
$(CC) $(OBJECTS) $(LDFLAGS) -o $@

.cpp.o:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp | $(OBJDIR)
$(CC) $(CFLAGS) $(CDEFINES) $< -o $@

$(BINDIR)/%.cl: $(KERNELDIR)/%.cl | $(BINDIR)
$(call COPY,$<,$@)

$(OBJDIR) $(BINDIR):
$(call MKDIR,$@)

clean:
$(RM) *.o
$(call RMDIR,$(OBJDIR))
$(call RMDIR,$(BINDIR))
66 changes: 42 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Profanity is a high performance (probably the fastest!) vanity address generator for Ethereum. Create cool customized addresses that you never realized you needed! Recieve Ether in style! Wow!

![Screenshot](/img/screenshot.png?raw=true "Wow! That's a lot of zeros!")
![Screenshot](/docs/img/screenshot.png?raw=true "Wow! That's a lot of zeros!")

# Important to know

Expand Down Expand Up @@ -65,7 +65,8 @@ xcode-select --install # skip if already installed
make
```

This produces `profanity2.x64` in the repository root. Works on both Intel and
This produces `bin/profanity2.x64`, with the two OpenCL kernels copied next to
it so the directory can be moved elsewhere as is. Works on both Intel and
Apple Silicon (M1/M2/M3/M4) Macs.

### Ubuntu / Linux
Expand Down Expand Up @@ -97,6 +98,23 @@ docker run --rm --gpus all ghcr.io/1inch/profanity2:latest --matching dead -z $P

Since the tool only needs your public key, that machine does not have to be yours. See [docs/VASTAI.md](docs/VASTAI.md) for renting a GPU on vast.ai and running the image there with your own parameters.

### Repository layout

```
src/ C++ sources of the host program
kernels/ the OpenCL kernels, keccak.cl and profanity.cl
bin/ what make produces: the binary and a copy of the kernels
build/ object files
docker/ the shipping image and its entrypoint
bench/ tooling that compares the speed of two revisions on one GPU
tests/ correctness tests and a microbenchmark for the mp-math kernels
docs/ build guides for Ubuntu and Windows, and the vast.ai guide
```

`make` copies the kernels into `bin/` because that is the first place the binary
looks for them, so it can be started from any directory. It still falls back to
the working directory, which is where releases before this layout kept them.

# Usage
```
usage: ./profanity2 [OPTIONS]
Expand Down Expand Up @@ -196,10 +214,10 @@ and better results:

```bash
# 0x00000... (as many leading zeros as possible)
./profanity2.x64 --leading 0 -z $PUBLIC_KEY
./bin/profanity2.x64 --leading 0 -z $PUBLIC_KEY

# 0xaaaaa... (as many leading "a"s as possible)
./profanity2.x64 --leading a -z $PUBLIC_KEY
./bin/profanity2.x64 --leading a -z $PUBLIC_KEY
```

### Exact pattern (`--matching`)
Expand All @@ -212,31 +230,31 @@ matches anything. The score is the number of matched fixed positions.

```bash
# 0xdead...
./profanity2.x64 --matching dead -z $PUBLIC_KEY
./bin/profanity2.x64 --matching dead -z $PUBLIC_KEY
```

**Suffix** — pad the beginning of a full 40-character pattern with `X` wildcards:

```bash
# 0x...999999
./profanity2.x64 --matching XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX999999 -z $PUBLIC_KEY
./bin/profanity2.x64 --matching XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX999999 -z $PUBLIC_KEY
```

**Prefix and suffix at the same time** — fix both ends, wildcard the middle:

```bash
# 0x1111...2222
./profanity2.x64 --matching 1111XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX2222 -z $PUBLIC_KEY
./bin/profanity2.x64 --matching 1111XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX2222 -z $PUBLIC_KEY

# 0xbad...bad
./profanity2.x64 --matching badXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXbad -z $PUBLIC_KEY
./bin/profanity2.x64 --matching badXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXbad -z $PUBLIC_KEY
```

**Arbitrary positions** — any mix of fixed characters and wildcards works:

```bash
# 0xXXXXcafeXXXX...XXXX (characters 5-8 are "cafe")
./profanity2.x64 --matching XXXXcafeXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -z $PUBLIC_KEY
./bin/profanity2.x64 --matching XXXXcafeXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -z $PUBLIC_KEY
```

Note: only results improving the best score so far are printed, so after a result matching
Expand All @@ -253,10 +271,10 @@ each one:

```bash
# Every address 0x1337...c0de found, not just the first one
./profanity2.x64 --exact 1337XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXc0de -z $PUBLIC_KEY
./bin/profanity2.x64 --exact 1337XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXc0de -z $PUBLIC_KEY

# Every address with at least five leading zeros
./profanity2.x64 --exact 00000XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -z $PUBLIC_KEY
./bin/profanity2.x64 --exact 00000XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -z $PUBLIC_KEY
```

The first matches take longer to appear than with `--matching` (partial matches are not
Expand All @@ -270,13 +288,13 @@ Score on the total amount of matching characters anywhere in the address:

```bash
# As many "0" characters as possible, e.g. 0x00aa0e050bb03c0b066e00c0f70a03d0d000b0d7
./profanity2.x64 --zeros -z $PUBLIC_KEY
./bin/profanity2.x64 --zeros -z $PUBLIC_KEY

# Only letters (a-f), e.g. 0xffcadbfaecfcdeaddeedabadfeedfacebeefcafe
./profanity2.x64 --letters -z $PUBLIC_KEY
./bin/profanity2.x64 --letters -z $PUBLIC_KEY

# Only numbers (0-9), e.g. 0x8896339129744478701529940603494328137361
./profanity2.x64 --numbers -z $PUBLIC_KEY
./bin/profanity2.x64 --numbers -z $PUBLIC_KEY
```

### Ranges (`--leading-range`, `--range`)
Expand All @@ -286,27 +304,27 @@ Score on characters within a given hex range, set with `-m/--min` and `-M/--max`

```bash
# Leading characters in range 0-1, e.g. 0x0110100...
./profanity2.x64 --leading-range -m 0 -M 1 -z $PUBLIC_KEY
./bin/profanity2.x64 --leading-range -m 0 -M 1 -z $PUBLIC_KEY

# Leading characters in range a-c, e.g. 0xcbabacc...
./profanity2.x64 --leading-range -m 10 -M 12 -z $PUBLIC_KEY
./bin/profanity2.x64 --leading-range -m 10 -M 12 -z $PUBLIC_KEY

# Characters in range 0-1 anywhere in the address
./profanity2.x64 --range -m 0 -M 1 -z $PUBLIC_KEY
./bin/profanity2.x64 --range -m 0 -M 1 -z $PUBLIC_KEY
```

### Other scoring modes (`--mirror`, `--leading-doubles`, `--zero-bytes`)

```bash
# Address mirrored around its center, e.g. 0x...abccba...
./profanity2.x64 --mirror -z $PUBLIC_KEY
./bin/profanity2.x64 --mirror -z $PUBLIC_KEY

# Leading pairs of identical characters, e.g. 0x00fFcc55...
./profanity2.x64 --leading-doubles -z $PUBLIC_KEY
./bin/profanity2.x64 --leading-doubles -z $PUBLIC_KEY

# As many zero BYTES (pairs "00" at even positions) as possible; such addresses
# save gas when used in calldata, e.g. 0x00815e00c0fd4a2d00ae00fa00e300ee00fc0034
./profanity2.x64 --zero-bytes -z $PUBLIC_KEY
./bin/profanity2.x64 --zero-bytes -z $PUBLIC_KEY
```

### Vanity contract address (`--contract`)
Expand All @@ -316,20 +334,20 @@ zeroth transaction** of the found account instead of the account address itself:

```bash
# Account whose first deployed contract gets a 0x00000... address
./profanity2.x64 --contract --leading 0 -z $PUBLIC_KEY
./bin/profanity2.x64 --contract --leading 0 -z $PUBLIC_KEY

# Account whose first deployed contract address has the most zero bytes
./profanity2.x64 --contract --zero-bytes -z $PUBLIC_KEY
./bin/profanity2.x64 --contract --zero-bytes -z $PUBLIC_KEY
```

### Benchmark and device control

```bash
# Measure hashrate without any scoring
./profanity2.x64 --benchmark -z $PUBLIC_KEY
./bin/profanity2.x64 --benchmark -z $PUBLIC_KEY

# Multiple GPUs are used automatically; skip a device (e.g. an integrated GPU) by index
./profanity2.x64 --leading 0 -s 1 -z $PUBLIC_KEY
./bin/profanity2.x64 --leading 0 -s 1 -z $PUBLIC_KEY
```

### Benchmarks - Current version
Expand Down
8 changes: 8 additions & 0 deletions bench/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# The benchmark image is built with this directory as its context, and the only
# file it copies in is run-benchmark.sh. Everything else just invalidates the
# layer cache when it changes.
README.md
logs
build.sh
publish.sh
prepare-native.sh
33 changes: 25 additions & 8 deletions bench/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
#
# Builds a self-contained image holding two revisions of profanity2 so their
# speed can be compared back to back on the same GPU. This image is a
# measuring tool, not the shipping image - see the Dockerfile in the
# repository root for that one.
# measuring tool, not the shipping image - see docker/Dockerfile for that one.
#
# docker build --build-arg REF_A=master --build-arg REF_B=pr/57 -t bench bench/
#
Expand Down Expand Up @@ -31,7 +30,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
# explicitly, otherwise a commit that only exists in a pull request cannot be
# resolved. The last step records whether the two revisions time a round the
# same way: if they do not, the speeds they print come from different clocks
# and the runner has to warn about it.
# and the runner has to warn about it. SpeedSample.cpp is looked for in two
# places because revisions from before the source tree was split into src/ and
# kernels/ keep it in the root of the tree.
RUN set -eu; \
echo "cachebust: ${CACHEBUST}"; \
test -n "${REF_A}" || { echo "error: REF_A build argument is empty" >&2; exit 1; }; \
Expand All @@ -55,7 +56,9 @@ RUN set -eu; \
git -C /repo rev-parse --short=7 "${sha}" > "/src/${slot}.sha"; \
echo "${slot}: ${ref} -> ${sha}"; \
done; \
if cmp -s /src/a/SpeedSample.cpp /src/b/SpeedSample.cpp; then \
timer_a="$(ls /src/a/src/SpeedSample.cpp /src/a/SpeedSample.cpp 2>/dev/null | head -1)"; \
timer_b="$(ls /src/b/src/SpeedSample.cpp /src/b/SpeedSample.cpp 2>/dev/null | head -1)"; \
if [ -n "${timer_a}" ] && [ -n "${timer_b}" ] && cmp -s "${timer_a}" "${timer_b}"; then \
echo same > /src/timer.state; \
else \
echo differs > /src/timer.state; \
Expand All @@ -75,6 +78,20 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
COPY --from=src /src /src
RUN make -C /src/a -j"$(nproc)" && make -C /src/b -j"$(nproc)"

# A revision from before the source tree was reorganized leaves the binary and
# the kernels in the root of its tree, a newer one leaves them in bin/. COPY
# cannot choose between the two, so both are collected here and the runtime
# stage sees a single layout.
RUN set -eu; \
for slot in a b; do \
mkdir -p "/out/${slot}"; \
if [ -d "/src/${slot}/bin" ]; then \
cp "/src/${slot}/bin/profanity2.x64" "/src/${slot}/bin/keccak.cl" "/src/${slot}/bin/profanity.cl" "/out/${slot}/"; \
else \
cp "/src/${slot}/profanity2.x64" "/src/${slot}/keccak.cl" "/src/${slot}/profanity.cl" "/out/${slot}/"; \
fi; \
done

# ---------------------------------------------------------------------------
# Runtime
# ---------------------------------------------------------------------------
Expand All @@ -100,10 +117,10 @@ ENV NVIDIA_VISIBLE_DEVICES=all \
NVIDIA_DRIVER_CAPABILITIES=compute,utility

# Each revision keeps its own directory: profanity2 loads keccak.cl and
# profanity.cl from the working directory and caches the compiled kernel
# there, so the two builds must never share one.
COPY --from=build /src/a/profanity2.x64 /src/a/keccak.cl /src/a/profanity.cl /opt/bench/a/
COPY --from=build /src/b/profanity2.x64 /src/b/keccak.cl /src/b/profanity.cl /opt/bench/b/
# profanity.cl from beside the binary and caches the compiled kernel there, so
# the two builds must never share one.
COPY --from=build /out/a /opt/bench/a
COPY --from=build /out/b /opt/bench/b
COPY --from=src /src/a.ref /src/a.sha /src/b.ref /src/b.sha /src/timer.state /opt/bench/

COPY run-benchmark.sh /usr/local/bin/bench
Expand Down
Loading
Loading