# HauhauCS FastMTP: a signed manifest that actually verifies

> Satyajit Ghana — Head of Engineering @ Inkers Technology
> canonical: https://ai.thesatyajit.com/articles/hauhaucs-qwen-fastmtp
> date: 2026-08-30
> tags: gguf, quantization, llama-cpp, multi-token-prediction, speculative-decoding, security
[HauhauCS/Qwen3.8-27B-Uncensored-HauhauCS-Aggressive-MTP-GGUF](https://huggingface.co/HauhauCS/Qwen3.8-27B-Uncensored-HauhauCS-Aggressive-MTP-GGUF)
is, by Hugging Face's own numbers, one of the more-downloaded community quants this site has looked
at: **1,061,687 downloads**, **752 likes**, **172.47 GB** spread across **21 files**. It is also, as
the name says, an uncensored derivative — HauhauCS's "Aggressive" refusal-suppression profile applied
on top of Qwen's own Qwen3.8-27B, with the card claiming 0 refusals across 465 prompts. That part of
the story is not new, and it is not this article's subject; abliterated Qwen3.8-27B derivatives are
already their own small ecosystem, and [the Qwen3.8-Flash-Next piece](/articles/qwen3-8-flash-next)
catalogued two others in it.

What is new — and, unlike the abliteration itself, fully checkable without touching model behavior
at all — is what else the repository ships. Sitting next to the eleven GGUF quants and a vision
projector are four files a quantizer almost never bothers with: a signed **release manifest**, a
signed **build-provenance** file for one specific artifact, the **Ed25519 public key** to check both
against, and a small **llama.cpp patch** — 27 lines added, one removed — against a pinned commit. None of that requires taking
HauhauCS's word for anything — the manifest names exact byte counts and hashes, the signatures are
checkable against a key shipped in the same repo, and the patch is a diff against a public commit
with a public history. So this article did the checking.

| | |
|---|---|
| Repo | [HauhauCS/…-Aggressive-MTP-GGUF](https://huggingface.co/HauhauCS/Qwen3.8-27B-Uncensored-HauhauCS-Aggressive-MTP-GGUF) · 1,061,687 downloads · 752 likes |
| Base | [Qwen/Qwen3.8-27B](https://huggingface.co/Qwen/Qwen3.8-27B) — dense, 64 layers, 48 Gated DeltaNet + 16 gated-attention |
| Size | 172.47 GB, 21 files · 11 text GGUFs, IQ2_M (10.32 GB) to Q8_K_P (31.46 GB) |
| Vision | separate `mmproj` BF16 projector, 931 MB, 334 tensors |
| FastMTP sidecar | `-FastMTP-32K.gguf`, 903 MB · trims the MTP head to a 32,768-token draft vocabulary |
| Authenticity | Ed25519-signed manifest + provenance, a raw public key, and a plaintext `SHA256SUMS` |
| Patch | one file, `src/models/qwen35.cpp`, +27/−1 lines, against `ggerganov/llama.cpp@4df29be4…` |
| License | Apache-2.0, inherited from Qwen3.8-27B |

<ModelCard repo="HauhauCS/Qwen3.8-27B-Uncensored-HauhauCS-Aggressive-MTP-GGUF" />

## The headline check: do the signatures actually verify

The method was plain: download `HauhauCS-RELEASE-MANIFEST.json`, its `.sig`, `FastMTP-PROVENANCE.json`,
its `.sig`, and `HauhauCS-FastMTP-Ed25519-PUBLIC.pem` directly from the repo's `/resolve/main/`, then
verify with Python's `cryptography` library — `load_pem_public_key` on the PEM, then
`pub.verify(sig, data)` on the exact downloaded bytes of each document.

<SignatureChain />

Both signatures verify. No exception, no fallback, no "couldn't check." And the public key itself
isn't just trusted on arrival — its DER fingerprint, computed locally from the downloaded `.pem`,
matches the `public_key_der_sha256` field the provenance file declares about itself, so the key doing
the verifying is provably the key the signed document says it should be.

## Checking the hashes without downloading 172GB of model weights

A signature only proves the manifest wasn't altered after signing — it says nothing about whether the
manifest's own claims about the files match the files. That part is checkable too, and cheaply. Every
small file the manifest covers — `FastMTP-PROVENANCE.json`, both `.sig` files, the PEM, the patch,
`README.md` — was downloaded and hashed directly: all five match the manifest's declared sha256 with
no exceptions. For the twelve GGUFs, downloading 172GB just to hash them defeats the point of having a
manifest at all, so this article cross-checked the manifest's declared sha256 against Hugging Face's
own file metadata instead, via `https://huggingface.co/api/models/<repo>?blobs=true`, which reports
each LFS file's sha256 without transferring the file. Every one of the twelve — including the vision
projector — matches.

There's a second, less obvious layer. Each GGUF entry in the manifest carries *two* hashes: a plain
`sha256` of the raw file, and a `canonical_tensor_sha256` computed over "sha256-sorted-name-type-shape-
payload" — HauhauCS's own stated algorithm name, not independently auditable here since the tool that
computes it isn't published. The idea, stated in the README's own authenticity section, is that the
plain hash "identifies byte-for-byte mirrors after renaming" while the canonical one "continue[s] to
identify HauhauCS tensors after metadata-only rewriting" — i.e. it should survive someone stripping or
editing the GGUF's key-value header while leaving the actual weights untouched, and change if the
weights themselves do. The field is present and internally consistent for every GGUF in the manifest;
whether the specific algorithm behind it does what it claims isn't something this article could verify
without the tool that produced it, so take the concept as sound and the implementation as unverified.

What isn't covered by the signed manifest is smaller than it sounds: itself, its own `.sig`, and
`.gitattributes`. A third file, `SHA256SUMS` — a plain, unsigned text ledger in the classic
`sha256sum` format — closes that gap: it lists the manifest and its signature alongside everything
else, and `sha256sum -c` against the small files downloaded for this piece reports every one `OK`.
Between the signed manifest and the plaintext ledger, every file in the repo except `.gitattributes`
has a declared hash checkable from at least one of the two.

## What FastMTP actually is, and where the MTP head comes from

Qwen3.8-27B is dense — every parameter active per token, no routed experts — which makes "where does
the MTP head come from" a fair question, since multi-token prediction usually shows up on MoE models
like DeepSeek-V3 or [Qwen3.8-Flash-Next](/articles/qwen3-8-flash-next). The answer is in the README's
own "Specs" section: Qwen ships a **native embedded MTP/NextN head on the dense model itself**, and
every text GGUF in this repo preserves it unmodified — nothing HauhauCS added. That head projects
directly onto the model's full, padded **248,320-token vocabulary**, same as the main output layer,
and it already works today with plain `--spec-type draft-mtp` on any of the target quants alone, no
patch required. If the mechanics of multi-token prediction as a training objective and a self-
speculative decoder are unfamiliar, [the MTP explainer](/articles/multi-token-prediction) covers both
Meta's parallel-head and DeepSeek's sequential-module flavors in more depth than this piece needs to.

**HauhauCS FastMTP is a separate, second checkpoint** — the 903 MB `-FastMTP-32K.gguf` — that reuses
the same idea but trims the head's output vocabulary down to a fixed, much smaller set of tokens. The
"32K" in the filename is the trimmed vocabulary size: 32,768, confirmed by the README's own diagnostic
example for a mismatched build ("expected 5120, 248320, got 5120, 32768") rather than asserted in
prose anywhere. A smaller output vocabulary means a smaller LM-head matmul on every draft step — the
whole point of a draft model is to be cheap — at the cost of the draft never being able to *propose* a
token outside that fixed 32,768. Running it requires the patch, because mainline `qwen35.cpp` has
nowhere to put a trimmed-vocabulary head.

<VocabTrim />

## The patch, read line by line

`HauhauCS-FastMTP-llama.cpp.patch` touches exactly one file, `src/models/qwen35.cpp`, and it applies
cleanly — checked here with `patch -p1 --dry-run` — against the exact commit its own provenance file
names, `ggerganov/llama.cpp@4df29be4f4c3673f428170fda944a5b19f743bb8`, fetched independently from
GitHub for the comparison. Two hunks, two jobs:

```diff
+    int64_t n_vocab_out = n_vocab;
+    const ggml_tensor * d2t_meta = ml.get_tensor_meta("d2t");
+    if (mtp_only && d2t_meta) {
+        n_vocab_out = d2t_meta->ne[0];
+        d2t = create_tensor(tn(LLM_TENSOR_D2T), { n_vocab_out }, 0);
+    }
     tok_embd = create_tensor(tn(LLM_TENSOR_TOKEN_EMBD, "weight"), { n_embd, n_vocab }, 0);
     output_norm = create_tensor(tn(LLM_TENSOR_OUTPUT_NORM, "weight"), { n_embd }, 0);
-    output = create_tensor(tn(LLM_TENSOR_OUTPUT, "weight"), { n_embd, n_vocab }, TENSOR_NOT_REQUIRED);
+    output = create_tensor(tn(LLM_TENSOR_OUTPUT, "weight"), { n_embd, n_vocab_out }, TENSOR_NOT_REQUIRED);
     if (output == NULL) {
+        GGML_ASSERT(!d2t && "d2t draft-vocab trim requires output.weight");
         output = create_tensor(tn(LLM_TENSOR_TOKEN_EMBD, "weight"), { n_embd, n_vocab }, TENSOR_DUPLICATED);
     }
```

The first hunk only trims `output.weight` when building the MTP-only graph (`mtp_only`, i.e. the
drafter, not the target model) *and* the loaded GGUF actually carries a `d2t` tensor — a GGUF without
one falls through unchanged. It also refuses to let a trimmed head fall back to the tied token-
embedding matrix, correctly, since that matrix is sized to the full vocabulary and can't stand in for
a smaller one. The second hunk, inside the MTP graph builder itself, takes the head's output over the
trimmed vocabulary and scatters it into a full-vocabulary tensor pre-filled with negative infinity,
using `d2t` as the index map — so the target model, verifying downstream, still sees an ordinary
248,320-wide logit vector, just one where most entries can never win.

The interesting part isn't the mechanism — it's where it came from. `LLM_TENSOR_D2T` and
`model.d2t` ("draft to target vocabulary mapping," in the field's own comment) are not new
infrastructure this patch invents; they already exist in llama.cpp's shared architecture code at that
same commit. A GitHub code search for `d2t` under `src/models` in `ggml-org/llama.cpp` turns up
exactly two files using it: `eagle3.cpp` and `dflash.cpp` — the dedicated draft-model architectures
behind [EAGLE-3](/articles/eagle-3-speculative-decoding) and [DFlash](/articles/dflash2), both already
covered on this site. `qwen35.cpp` itself has no `d2t` reference before this patch. So HauhauCS's
contribution here is narrow and precise: not a new vocabulary-trimming idea, but the first wiring of
llama.cpp's existing one into a dense model's own embedded MTP head, rather than into a purpose-built
external drafter.

## Does it actually go faster?

Here the checking has to stop being independent, because reproducing it would mean running the model.
HauhauCS's own numbers, measured on one RTX PRO 6000 Blackwell (96 GB), one lane, `--no-mmap`, full
CUDA offload: FastMTP at depth 3 reaches up to **3.02x document throughput and 1.93x reasoning
throughput** against MTP disabled entirely, and up to **35.2% more document throughput and 21.1% more
reasoning throughput** than the native embedded MTP head running at depth 2. Every FastMTP run is
reported to reproduce the corresponding embedded-MTP output token-for-token — the expected result,
since the target model still verifies every drafted token regardless of which head proposed it, and a
correctly-implemented draft head can only change speed, not output. That claim, and the underlying
tok/s table across all ten quants, is self-reported, single-hardware, and not reproduced by this
article — unlike the signatures and hashes above, there's no cheap independent way to check a
throughput number without the GPU it was measured on.

## The K_P quant ladder: checking one more claim

The card makes a second, smaller, checkable claim about its own custom "K_P" quants: each one "bumps
quality up by one or two quant levels at only around 5-15% more size than the base quant." Its own
Downloads table gives both numbers directly — the real K_P file's bits-per-weight, and a reference
bpw for the standard llama.cpp quant type sitting right underneath it — so this is arithmetic, not
another benchmark to trust blind.

<QuantLedger />

Three of the five checkable pairs land inside the stated band. Two don't: Q5_K_P is a few points under
the 5% floor, and Q3_K_P is barely bigger than plain Q3_K_M at all. None of this touches the size and
hash checks earlier in this piece — every file's bpw and byte count match what's actually on Hugging
Face — it's specifically the comparison to the *standard* quant types that the card's own numbers
don't uniformly support.

## The vision claim, checked against what's actually shipped

The repo's tags include `multimodal` and `vision`, and a vision claim on a GGUF release is exactly the
kind of thing worth checking against the file list rather than the tag list: a GGUF text model needs a
separate multimodal projector (`mmproj`) file to actually accept image input, and plenty of releases
carry the tag without carrying the file. This one does carry the file —
`mmproj-Qwen3.8-27B-Uncensored-HauhauCS-Aggressive-BF16.gguf`, 931 MB, 334 tensors, its sha256 present
in the signed manifest and matching Hugging Face's own metadata like everything else checked above.
The vision claim holds up against what's actually in the repository, for whatever the underlying
Qwen3.8-27B vision tower is itself capable of — a question this article didn't re-test.

## What this is, and isn't

**Verified directly.** Both Ed25519 signatures check out against a public key whose own fingerprint is
independently confirmed. Every declared hash — for text files by direct download, for the twelve
GGUFs against Hugging Face's own LFS metadata — matches. The patch applies cleanly against the exact
commit its provenance file names, and the mechanism it adds is a real, pre-existing llama.cpp
convention already used by two draft-model architectures this site has covered, not a novel or
unverifiable trick. The vision projector the tags promise is actually in the file list.

**Self-reported, not independently reproduced here.** The speedup numbers — the 3.02x/1.93x headline
and the full per-quant table — come from HauhauCS's own single-GPU benchmark. Checking them would mean
running a 172GB download through the patched runtime on matching hardware, which this piece didn't do.

**Checked and found uneven.** The K_P "5-15% more size" framing holds for three of five comparable
pairs and misses low for two, most notably Q3_K_P.

The uncensoring is the reason this repository exists and the reason it has a million downloads; it is
also the one part of the release this article isn't going to explain, demonstrate, or evaluate. What
made it worth a full pass is everything sitting next to it: a signed manifest and a signed provenance
file are not standard practice for a community requant, checking them costs nothing but bandwidth and
a public key, and in this case, they hold up.
