run.sh downloads public 4-bit weight files of Llama 4 Maverick, generates the commitment to them,
compares it with the published one, proves one request and checks the proof. It asks for one NVIDIA
H100 with 80 GB, 330 GB of host memory and 245 GB of disk space, and takes hours.
docs/quickstart.md, route 4 has
the short form of this page. How these public weights fared in the Lean library's two worst-case
checks (neither is cp_commit's), by a program of this project, and what that doesn't show:
docs/limits.md.
None of Meta's files is in this repository. For this model it has three things: the address of the weight files, the code that generates the commitment, and the commitment, as its commitment ID. The other files here are checksums and digests to compare a run with, the seed file and the figures that the script prints and checks for.
| file | what it is |
|---|---|
run.sh |
the script; without arguments it prints its stages and options. It has the weight files' address and revision, and calls the code that generates the commitment: bin/weight_sums, scales/ and cp_commit |
weights.sha256 |
the SHA-256 checksums of the five weight files |
public-seed.bin |
the published seed file, 32 bytes |
figures.txt |
measured times and peaks of host memory, which run.sh prints, and the host memory and disk space that it checks for |
expected.txt |
the commitment ID, and the SHA-256 digests of four files that a run generates: wsums.txt, KL.bin, key.bin and leaf/0.bin (where they come from) |
8-bit/, 16-bit/ |
weights.sha256, figures.txt and expected.txt for the same publisher's 8-bit and 16-bit files |
- The weight files (232 GB). They are a third party's 4-bit conversion to GGUF
(
unsloth/Llama-4-Maverick-17B-128E-Instruct-GGUFon Hugging Face) of Meta'smeta-llama/Llama-4-Maverick-17B-128E-Instruct. The conversion's card has the fieldslicense: otherandlicense_name: llama4, and it carries the text of the Llama 4 Community License Agreement as the text of an access form. Thatllama4means this agreement is this repository's reading: sources. You fetch the weight files from their publisher, with the stagedownloador by yourself. - What a run computes from the weights: the fitted scales and parameter file, the commitment's
public key directory, a proof. Of these the repository has only digests and the commitment ID, so
that as little as possible of what it publishes derives from Meta's model (what else does, or
may). So to check a proof for Maverick you
first generate the public key directory yourself: run the stages up to
compare. - The calibration set. You make it with
scales/make_calibration_set.py, from three published files that you fetch yourself: the raw training split of WikiText-2 (the corpus that S. Merity, C. Xiong, J. Bradbury and R. Socher describe, arXiv 1609.07843; fromSalesforce/wikitexton Hugging Face, whose listing gives its licence as CC BY-SA 4.0 and also lists CC BY-SA 3.0 and the GFDL) and the tokenizers of Llama 2 and Llama 4. The two tokenizers open only to users whose request for access their publisher, Meta, has granted, each at its own repository on huggingface.co, and each request includes accepting that model's licence (scales/README.md lists the three files).
The commitment is made with -public-weights and a published file of 32 bytes, so anyone who has
the weight files and makes the calibration set can remake it. Such a commitment does not hide the
weights, and no privacy between a batch's clients is claimed: it is no example of hiding at work.
For this reason the script asks you to declare each weight file public (what that option gives
up). Do that only for weights that are public: with
this option the weights are not hidden. Without -public-weights, cp_commit
draws the seed itself (weight hiding).
Type every line on this page in the repository's top directory, under one ordinary account, never as
root or under sudo (why). If root is the only
account, make another first (Install). The script's messages
name sudo; that is no advice to use it.
- GPU: one NVIDIA H100 with at least 80,000 MiB of memory, on which nothing else is running, and
its driver: GPU 0, unless
CUDA_VISIBLE_DEVICESnames another. - Host memory: 330 GB available for
commit, 290 GB forprove(limits that the script does not see). - Disk space: 245 GB in round figures: 232.1 GB for the weight files, and 10 GB for
commitand 1 GB forprovein the work directory, which must be on a local disk. - For the build: what route 3 lists, with the pinned compiler.
- Also: a CPU with the SHA extensions;
curl,flock,sha256sum,ldd, and GNUfind,statandreadlink. - Python 3.13 with the packages that
requirements.txtpins. - Meta's grant of access to the tokenizers of Llama 2 and Llama 4, for the calibration set: ask before you rent a machine.
- Hours. After the download, the longest steps are the build, measured at 29 minutes† on 11 CPU
cores, and
commit, at 43 minutes†. In one run† on a shared machine four times lay above those infigures.txt(which).
The stage needs prints all amounts and times, and checks the machine for most of this: not for the
build's needs, Meta's grant or the hard links that fit needs in the weights directory, and of the
Python packages only for the versions of torch, numpy and gguf. The times also depend on your
disk: cp_commit and cp_prove have the system drop the weight files from its file cache as they
load them, so each may read the 232 GB from the disk again, and cp_commit twice. No option turns
this off.
These two lines install the packages into a new directory VENV and put its python3 first on
PATH:
python3.13 -m venv VENV && VENV/bin/pip install --require-hashes -r requirements.txt
source VENV/bin/activate
In a new shell, run the source line again. Ubuntu 24.04 comes with Python 3.12: if python3.13 is
missing, install it alongside the system Python, for example from the sources at
python.org.
W=$(mktemp -d /var/tmp/maverick.XXXXXX) && M="$W/work" F="$W/weights" && echo "M=$M F=$F"
(umask 022; mkdir "${F:?first run the line with mktemp}" && while read -r sum name; do python3 -I -c 'import os, sys; sys.tracebacklimit = 0; os.write(os.open(sys.argv[1], os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o644), (sys.argv[2] + "\n").encode())' "${F:?}/$name.weights-are-public" "$sum $name" || exit 1; done < examples/maverick/weights.sha256)
python3 scales/make_calibration_set.py TRAIN_PARQUET LLAMA2_TOKENIZER_JSON LLAMA4_TOKENIZER_JSON "${F:?first run the line with mktemp}/calibration_set.npy"
examples/maverick/run.sh all "${M:?first run the line with mktemp}" --weights "${F:?first run the line with mktemp}"
- The first line picks two new directories under
/var/tmp:M, the work directory, andF, the weights directory. Many systems delete old files under/var/tmp, so to keep yours, use another directory. In a new shell, paste the printedM=… F=…line instead of running this line again. - With the second line you declare that the weights are public (The seed is
published): for each weight file it creates a file with the same name
plus
.weights-are-public. Without these declarations the script stops. - The third line makes the calibration set. It needs no GPU, so you can make the set on another
machine before you rent one, and copy it into place. Its three words in capitals are the paths of
your copies of the three files. It must end by printing
the set is as expected, with exit code 0: the script stops (exit code 1) without the set, and at a set with another SHA-256 than the one that it holds. The program overwrites no file, so move yours away before you make the set again. - The fourth line checks the machine and then runs the stages in order. It prints each step's command, the expected result and the actual one, and stops at the first step where they differ.
Whichever directories you use, M must be on a local disk, the directory above it must exist, and
neither M nor F may be inside the other. The script rejects M if another account may be able
to change it or a directory above it, and F too while weight files are missing. The full path of
M may contain only letters, digits, /, ., _ and -. Only the account that made a work
directory can use it again. From fit on, both directories must stay in place.
To run it in the background, as a coding agent should, use this line in place of the last line under Run it:
{ examples/maverick/run.sh all "${M:?}" --weights "${F:?}"; echo "status $?"; } >>"${M:?}.out" 2>&1 &
The run is over when the last line of $M.out is status N. It also stops if the terminal closes,
so over ssh use tmux or screen.
If all goes well, the compare stage prints Your commitment is the published one., and the exit
code is 0. Near the end the script repeats cp_verify's output, with the line on proof of work and
the error bound (when to accept). The last lines look like
this:
expected: exit status 0 and the last line YES
got: exit status 0 and the last line YES
The proof is /var/tmp/maverick.XXXXXX/work/proof.1/out/example.proof.
The next token's id is the 4-byte number in example.y, next to it.
examples/maverick/run.sh: stage prove finished as expected, in N s
examples/maverick/run.sh: your files are in /var/tmp/maverick.XXXXXX/work
The request is 1,024 token ids from a formula, and the proof covers one token, the next one (what an accepted proof means).
all runs these stages in this order. Each stage from fit on needs what the stages before it
made.
| stage | what it does |
|---|---|
needs |
prints what the stages need, checks the machine for most of it (You need), and looks for the declarations and the calibration set; it writes nothing |
build |
builds the verifier, the GPU programs and bin/weight_sums |
download |
fetches the five weight files at a pinned revision; a second call continues incomplete files |
checksums |
compares the files' SHA-256 checksums with weights.sha256 |
fit |
computes the quantization scales from the files and the calibration set, on the GPU, compares the digests of wsums.txt and KL.bin with expected.txt, and asks cp_verify, in a planning call, whether it accepts the fitted files |
commit |
generates the commitment |
compare |
compares the commitment ID and the digests of four files with expected.txt |
prove |
proves the example request and checks the proof with cp_verify against the commitment ID in expected.txt |
examples/maverick/run.sh <stage> <work directory> --weights <directory> [--width 8|16] [--limits <file>]
Any stage name works in place of all. Go on to the next stage only after exit code 0: a stage then
prints stage NAME finished as expected, and needs prints
this machine has what the stages after build need; nothing was written. The two options have
sections of their own: --width and
--limits.
The script re-executes itself with a nearly empty environment, so LD_LIBRARY_PATH does not reach
anything it runs. It keeps only PATH, CUDA_VISIBLE_DEVICES, SUDO_UID, three proxy variables
(https_proxy, all_proxy, no_proxy, in lower or upper case) and curl's two certificate
variables.
The first call of a stage other than needs creates the work directory, closed to other accounts.
fit, commit and prove each write to a new numbered subdirectory, and a later stage uses the
newest finished fit and the newest complete commitment. Everything stays until you remove it, a
stopped call's files too.
| path | what it is |
|---|---|
fit.N/ |
config/, the configuration: the fitted policy.txt and KL.bin, and layout.txt |
commitment.N/ |
ivk, the public key directory; isk, the secret key directory; cp_commit.log, which has the commitment ID |
proof.N/ |
in/example.req, the request; out/example.y, the next token's id; out/example.proof, the proof |
logs/ |
run.N.log, a call's output (needs alone writes none), and the tools' logs |
Two stages also write into the weights directory. download creates the weight files and, next to
each one that it starts, an empty file with the same name plus .download-may-append. fit creates
wsums.txt and fold.txt, two small text files that the programs read there, where nothing has
these names; for that the file system must offer hard links.
The script does not remove, replace or rename any file that existed before the call, except the
builds' output, in the repository, and the programs' caches, in the work directory. It appends to
such a file in two cases: download to an incomplete weight file that has its
.download-may-append file, and cp_prove to the commitment's counter files (count.bin).
The exit code is then 1 or 2; 2 stands for a wrong command line, directory or limits file. The last
message begins with examples/maverick/run.sh:. It says what stopped the run and, in most cases,
what to do next. A call that the script cannot read, such as one with an unknown stage, gets the
usage text instead. Mostly you fix the cause and run the same line again.
A repeated all checks the machine again. It then skips build if the programs are built, weight
files that are complete, checksums and fit after a finished fit, and commit after a complete
commitment.
Ctrl-C at the terminal goes to the script and to what it started. If the script alone is ended, what
it started runs on, and until that ends a second call that would write to the work directory stops
(another call of this script is still running).
The fit may not repeat on your machine. Your commitment
ID matches the published one only if your quantization
scales match too, and fit computes them in float32 on
the GPU, where rounding can differ between GPU models, drivers and torch's CUDA libraries. If
fit stops because your scales file, KL.bin, differs, reinstall the pinned packages, or use
another H100 machine; no later stage accepts different scales. A difference in the fitted lines of
the parameter file policy.txt shows only in compare, as another commitment ID.
Run the first line under Run it, set F to your files' directory (in a new shell, again
after you paste the printed line), and run the fourth line with needs in place of all. Once the
machine passes its other checks, that call stops (exit code 1) where the declarations are missing,
with a command that creates them, and then where the calibration set is missing, with the command
that makes it. After both, run the fourth line as it stands: download fetches nothing, and
checksums checks your files.
The script prints these commands only if no other account can write in the weights directory or replace a directory above it, and none owns anything in it. Yet with complete weight files it goes on in such a directory, and has no defence against another account that writes there while it runs.
The directory must hold the five files themselves, under the names in weights.sha256, and no other
*.gguf file: cp_commit and cp_prove read every *.gguf file in it, follow no symbolic link
there and take no file that has a second hard link. So copy files that sit behind links, as in a
Hugging Face cache, into one directory first.
In needs, and before cp_commit and cp_prove start, the script stops if less host memory is
available than it asks for. As available it counts the smaller of MemAvailable in /proc/meminfo
and, in a container, what is left under the container's memory limit. Under cgroup v1, or if it
cannot read the memory in use, it counts the whole limit as available.
It sees a limit only in the container's own files, /sys/fs/cgroup/memory.max or, under cgroup v1,
/sys/fs/cgroup/memory/memory.limit_in_bytes. So it misses a limit on a cgroup above the
container's, and one on a job without a cgroup namespace, as a job scheduler such as Slurm can set
it. There, ask the scheduler yourself for the memory that needs prints. Neither amount covers what
other processes take after the script has looked.
Each amount is the largest measured peak plus 20 GB, rounded up to a multiple of 5: 310 GB† while
cp_commit ran, 268 GB† while cp_prove ran (file cache not counted). While cp_commit checks the
weights against wsums.txt, it holds up to six buffers of 10.74 GB each in host memory; how many
varies, also between runs on one machine. Its peak varied between runs†, from 299 GB to 310 GB.
commit and prove have not been run with only these amounts: in the measured runs† the script
counted 452 GB as available.
The published commitment's acceptance policy is exact match: a checked token is accepted only if it
is the integer model's top choice. commit --limits FILE generates a commitment under a clipped-gap
policy instead, which is meant for replies that a floating-point engine served (acceptance
policies). The file contains exactly the three lines
C N, theta N and cap N, as integrations/vllm/integer_model/examples/fit_limits.py prints
them (how to fit
them).
A work directory takes one commitment, and all takes no limits, so call the stages one by one, in
a work directory that has no commitment. If the lines under Run it have built the
programs and fetched the weight files, the first line below chooses a new work directory next to the
old one. If not, run the first three of those lines, then the fourth three times, with build,
download and checksums in place of all, and skip the first line below. Set L to the path of
your limits file. In a new shell, set M to what the first line below printed: with the first M,
compare and prove would run on the published commitment.
M="${M:?first run the line with mktemp}-limits" && echo "M=$M"
examples/maverick/run.sh fit "${M:?}" --weights "${F:?}"
examples/maverick/run.sh commit "${M:?}" --weights "${F:?}" --limits "${L:?}"
examples/maverick/run.sh compare "${M:?}" --weights "${F:?}"
examples/maverick/run.sh prove "${M:?}" --weights "${F:?}"
- Before
cp_commitstarts,commitprints your limits, asexpected: C N, theta N, cap N. If that line is missing, the call was run without--limits: interrupt it with Ctrl-C and run the line again. Once such a call has finished, the work directory has the published commitment and takes no other. - The commitment ID covers the limits, so it is your own: nothing is published to compare it with,
and nothing checks the fitted lines of
policy.txt, which it also covers. The example request has no reply, so aYEShere shows nothing about your limits. To prove replies under them, go on with Prove replies that were served earlier, with the five shell variables thatproveprints.
The publisher of the 4-bit files offers the same model in wider formats, in the same repository, and
run.sh takes two of them. Add --width 8 or --width 16 after the weights directory and before
--limits, at every stage, and in the second line under Run it write
examples/maverick/8-bit/weights.sha256 or examples/maverick/16-bit/weights.sha256. Call needs
first, and go on to fetch hundreds of gigabytes only after it has ended well.
| no option | --width 8 |
--width 16 |
|
|---|---|---|---|
| the publisher's directory | UD-Q4_K_XL (4 bits) |
Q8_0 (8 bits) |
BF16 (16 bits) |
| weight files | 5, 232 GB | 9, 426 GB | 18, 801 GB |
host memory that commit asks for |
330 GB | 545 GB | 955 GB |
host memory that prove asks for |
290 GB | 505 GB | 915 GB |
| disk space in all | 245 GB | 440 GB | 815 GB |
weights.sha256, figures.txt, expected.txt |
in this directory | in 8-bit/ |
in 16-bit/ |
Use a weights directory and a work directory of their own for each width, each weights directory
with its own copy of the calibration set. Every stage stops (exit code 2) in a work directory that a
call with another width created. But in a new work directory download without the option, into a
weights directory that holds no weight file, starts to fetch the 4-bit files: stop it with Ctrl-C,
and go on in two new directories. The script removes nothing of what it has fetched.
prove gives cp_prove other values for -memory (the
option): lean,tensor-rooms=6 at 8 bits, and
lean,tensor-rooms=0,experts-by-layer,experts-rooms=1 at 16 bits.
How far this has been run. At each width one run† has made the commitment from the real files,
on one machine, by one call each of needs, fit, commit and compare (not with the script as
it is here). It gave the five values in that width's expected.txt. For three of them, the
commitment ID and the digests of key.bin and leaf/0.bin, it is the only run: nothing shows that
a second run, or another machine, reproduces them. Its compare had no stored commitment ID to
compare with and stopped there, so on the real files no call of compare with --width has
finished with exit code 0. build, download, checksums, prove and all have not run with
--width on the real files, and the files' address has not been tried against Hugging Face.
The peaks in the two figures.txt, and the times of cp_commit and cp_prove, come from one run†
at each width without this script, on a machine with 2,018 GB of host memory; each proved one
request, and cp_verify accepted the proof. sums_time and calibrate_time come from fits on
other machines, as their lines say. The two amounts of host memory lie about a tenth above the
peaks; neither run had as little.
Eight runs of this route on the real 4-bit weight files gave these five values, and in each
cp_verify accepted the proof (by the runs' records, which are not in this repository).
- One run was on the released programs. It went through all the stages of
run.sh all, in their order, on one H100: the run reported that it ended with exit code 0, that the five values came out as inexpected.txt, byte for byte, that the commitment ID was the stored one, and thatcp_verifyended withYES. The build stage was skipped, because the programs were built beforehand from these sources; the download stage fetched nothing, because the five weight files lay there beforehand at their checksums; and the tools that the stageneedsasks for were installed beforehand, so building, downloading and installing the tools were not exercised. The script that ran differs from this repository's in comments and messages. - Seven were not on the released programs.† One went through the whole route and ended with exit
code 0, with a calibration set made for it by
scales/make_calibration_set.pyand programs built beforehand; it did not follow this page in every point, and this page does not tell in which. The other six used forms of the script that differ from the one here. One of them went through all the stages ofrun.sh all, in their order, on one H100, and ended with exit code 0, with the build stage skipped and nothing fetched. Three called the stages one by one, withoutbuildanddownload, on three machines of one kind: one H100 with 80 GB, in a container with 24 CPU cores and a memory limit of 463 GB (row SO-6.5 of docs/limits-all-rows.tsv). Two were one call ofalleach, in which all eight stages ran. - Fetching is not shown.
downloadhas never fetched a file from Hugging Face: in every run the weight files were already in place. Two of the calibration set's three source files were copies from other addresses than the pinned ones, with the pinned checksums. In the two runs byallin which all eight stages ran† the Python packages did not come from the public index, and another tool had installed the CUDA toolkit. - Times above the stored ones. In one of those two runs,† on a machine that it shared with other
work, four of the seven times lay above their lines in
figures.txt: those of the build, ofscales/calibrate.py, ofcp_commitand of its worst-case check. No peak of memory and no amount of disk space did. For the four times above their lines no cause is shown (row RES-36 of docs/limits-all-rows.tsv). In the run on the released programsscales/calibrate.pytook longer than its line infigures.txtsays.
Equal values show that generating the commitment repeats on another machine of that kind. They do
not show that the commitment is right, and they say nothing about another GPU model, driver, tool
chain or set of CUDA libraries. For two of the runs† the platform is recorded: programs built with
nvcc 13.2.86 and g++ 13.3.0, which loaded cuBLAS and cuBLASLt 13.4.1.3, the CUDA runtime 13.2.86 and
the driver's libcuda 580.178.04 (torch has CUDA libraries of its own).
Each time and peak in figures.txt† is the largest of the three runs that called the stages one by
one, rounded up, except sums_time, the range over all three, and build_time, which comes from a
separate build on another machine. The file's line taken_with, which needs prints, names those
runs' programs in its own words. In these runs a separate process kept dropping the weight files'
pages from the operating system's file cache while the script read them.
† Not on the released programs: which kinds of result these are.