Tech

Port Mortem 2026: what it takes to prove a rewrite actually behaves

148 teams had 72 hours to port a real, battle-tested library into a new language and prove the rewrite behaves exactly like the original, byte for byte.

August 24, 2026
.
7 min read

Most porting projects stop at "it compiles." Port Mortem asked for the opposite: pick a real, widely used library, rewrite it in a language it was never written in, and prove — with hashes, differential fuzzing, and honest benchmarks — that the rewrite behaves exactly like the original. Not "close enough." Byte for byte.

Over 72 hours, 148 teams took that challenge into C, TypeScript, Python, JavaScript and Go libraries and brought back verified ports in Rust, Go and C++. The rule that separated the field wasn't cleverness. It was whether a team could show its work: pinned test suites hashed so nobody could quietly edit them, fuzzers run for hours instead of minutes, and benchmarks that reported the losses along with the wins.

What participants built

The top submission, 0xicbor from Cause of Death, took on Intel's tinycbor — 6,456 lines of C implementing RFC 8949 CBOR encoding — and rewrote it in Rust while keeping the original C ABI intact. That last part matters more than it sounds: existing C code linking against tinycbor can swap in the Rust binary without recompiling a single caller. The team verified nearly 5,000 original test cases, pinned their claims with SHA-256 hashes, and documented every one of roughly 80 unsafe blocks rather than burying them. One judge independently re-checked three of the team's claims against the actual repository before scoring it — the hash pins, the unsafe count, and a filed upstream GitHub issue all held up.

Second place went to cron-parser-go from Team Rocket, a Go port of the TypeScript cron-parser library that resolves cron expressions into real run times across timezones and daylight-saving transitions. The standout decision here was building a WebAssembly bridge for the sole purpose of running the original TypeScript test suite directly against the Go implementation — 280 of 280 unmodified upstream tests passing, with the original files cryptographically hashed to prove nobody edited them to make that number easier to hit. Along the way the team ran differential fuzzing against the real library, found five real bugs in the upstream project, and got the fixes merged.

Third place, blackfriday-2-rust from Doniyor's Team, ported Go's Blackfriday v2 Markdown processor to Rust — filling a genuine gap, since existing Rust Markdown crates target CommonMark and Blackfriday's older Markdown.pl-descended quirks aren't the same dialect. Because Blackfriday is pure bytes-in-bytes-out with no filesystem or network calls, differential testing against the Go original gave 100% signal with zero test flakiness, and the team used that clean signal to run extensive fuzzing that surfaced real infinite-loop bugs in specific edge cases.

Beyond the podium, a cluster of submissions pushed the verification bar even further. tinycolor-rs from AIBros ported the popular JavaScript color library to Rust and compiled it to a live, in-browser color lab — but the more interesting work was underneath. The team discovered that Math.pow isn't bit-identical across JavaScript engines, narrowed the divergence down to a specific 256-integer domain, and tabulated exactly how V8 behaves on it before deciding whether their Rust port needed to reproduce that quirk or could safely diverge from it. A 300-second fuzzing run produced over 31 million comparisons at bit-level IEEE-754 precision with zero divergences — and when a handle-table memory leak only surfaced after 4.6 million constructed color objects during a longer run, the team documented it rather than quietly shipping a shorter, cleaner-looking log.

decimaljs-go from Code Resurrector ran all 22,658 of decimal.js's own assertions byte-for-byte against its Go build, hashed so the test files couldn't be edited to fit, and filed a real bug against the upstream decimal.js test suite itself — an undefined loop variable causing a ReferenceError on a clean checkout. And JITI-GO from team Raptors took on one of the harder targets in the field: porting jiti, a JavaScript transpiler, by moving the transform engine into a long-lived Go daemon built on esbuild's native API, with a thin Node adapter that hosts only the original unmodified tests. The architecture makes the equivalence guarantee unusually crisp for a tool that had to be substantially rewritten rather than mechanically translated, and the team's differential fuzzer reported all 174 divergences it found transparently — including the ones where their port was intentionally stricter than the original, working against their own score rather than for it.

A recurring theme across the strongest entries was what one judge called the "reward-honest-numbers spirit": teams that led with their slowdowns instead of burying them, that disclosed the exact mechanism behind a performance gap instead of leaving a scary headline number unexplained, and that treated a discovered-but-unobservable defect as something to document rather than quietly fix and forget.

Ports of C libraries brought a different kind of honesty test. cJSON -> Rust from beTheNoob rebuilt cJSON with an ABI-identical struct layout so the original C test suite could link straight against the Rust binary and run unmodified — 22 of 22 Unity test binaries passing across eight consecutive green runs, hash-pinned so the test files couldn't be quietly edited. Getting there meant keeping a C-style tagged struct with raw linked-list pointers instead of a safer, more idiomatic Rust enum, a deliberate tradeoff the team documented rather than hid. Along the way they caught their own false positive — a missing build flag meant only one of the 22 original tests was actually executing, discovered by counting assertions rather than trusting a green checkmark — and reproduced a real CVE (CVE-2025-57052) as a regression test. Over 70 million differential-fuzzing comparisons against the live upstream build turned up zero unexpected divergences, and one genuine string-printing bug the fuzzer caught went from 192,000 divergences to zero after a one-line fix.

Beyond the main competition, a Write-Up Side Quest asked participants to document their porting process honestly rather than pitch it. The strongest entries treated a failed hypothesis as content worth keeping: one write-up replayed nearly 140,000 real calls for byte-identical verification and reported a benchmark where the port ran measurably slower on one operation, framing an unqualified benchmark table as marketing rather than evidence. Another documented four separate root-caused bugs surfaced mid-port, including undefined behavior that compiled cleanly on one compiler and failed outright on another. A third reported a genuine borrow-checker fight forced by a self-referential data structure, alongside a full latency table that openly disclosed a regression instead of omitting it.

Evaluation approach

Submissions were scored on four published criteria — Functionality & Reliability, Behavioral Equivalence, Code Quality, and Innovation — by a panel of engineers spanning Nvidia, Amazon, Google, IBM, Microsoft, Coinbase, Oracle and more. Anshul Kumar Purohit (IBM) and Karthik Kapula (ICS Global Soft Inc) reviewed some of the most heavily instrumented submissions in the field, alongside Vijay Anthony Richard (Amazon), Duygu Unlu (Fametech), Janardhana Naidu Kola (ADP), Tanay Chowdhury, and Alok Kumar (Nvidia). Judging leaned on primary evidence over trust: reproducing test runs locally, checking hash pins against the actual repository, and re-deriving a team's headline numbers rather than taking a README's word for them.

Engineering challenges

The hardest problems in Port Mortem weren't really about syntax translation. They were about behavioral equivalence in the places language semantics quietly diverge — JavaScript's Math.pow not agreeing bit-for-bit across engines, Go's date-rollover behavior differing from Luxon's clamping at month boundaries, or a JSON transport layer silently losing the distinction between NaN, -0, and Infinity unless a team went out of their way to preserve it. Teams that scored well treated these as the actual work of the hackathon rather than edge cases to paper over.

The same pattern showed up in test integrity. Several teams built adapter layers whose entire purpose was letting an original, unmodified test suite run directly against the new implementation — a WebAssembly bridge, a JSON-RPC daemon, a thin process shim — and then hashed the original test files so a judge could verify nobody had quietly edited a failing assertion out of existence. That extra layer of infrastructure, built purely for verification rather than functionality, ended up being one of the clearest signals separating the top of the field from submissions that only asserted equivalence.

Ports targeting C libraries surfaced a genuine design tension that judges weighed carefully rather than penalizing outright: ABI compatibility and idiomatic code quality pull in opposite directions. Keeping a C-style tagged struct and raw pointers, instead of rewriting the same data as a safe Rust enum, is what let an unmodified C test suite link directly against a Rust binary — but it's also, by definition, a less idiomatic port. The teams that scored best on this axis weren't the ones that avoided the tradeoff; they were the ones that named it explicitly, confined the resulting unsafe code to the FFI boundary, and explained in their documentation exactly why compatibility won out over cleanliness in that specific spot.

Looking forward

Port Mortem's premise was simple to state and hard to deliver on: languages die, but the code inside them doesn't have to. What the field proved is that porting real software well isn't a translation exercise — it's an evidence-gathering one, where the honest disclosure of a slowdown or a divergence carries more weight than a clean-looking demo. That standard is worth carrying into whatever comes next.

Related Blogs

No items found.