I am a software developer based in Indonesia, working mostly in C, C++, and Rust on Bitcoin Core, libsecp256k1, zero-knowledge virtual machines, compilers, and security-critical firmware.
I focus on correctness at the byte, register, and algebraic level: where boundary arithmetic overflows, where elliptic curve additions hit degenerate points at infinity, and which regression harness kills subtle mutants. I also build tools for inspecting binary structures, formal limb bounds, and replaying edge failures.
Email · LinkedIn · PR history
| Project | What I changed |
|---|---|
| LLVM / AMDGPU | Prevented image-load merges that lose TFE/LWE status results. Added MIR regression tests for the affected ordering. |
| Microsoft / MsQuic | Fixed reversed source and destination arguments when copying a header-protection sample after a receive batch splits. |
| Trezor Firmware | Cleaned up IPC message queues on task termination to prevent dangling queue handles and stale message leaks across tasks. |
| Consensys / gnark-crypto | Returned ErrZeroNbDigests on empty digest slices in batch KZG opening and verification, avoiding division-by-zero panics. |
| Vulkan Validation Layers | Added a bounds check to stop descriptor validation reading past a smaller pipeline-layout binding. |
| Bitcoin Core / secp256k1 | Added constant-time test coverage for schnorrsig_sign_custom, including custom nonce callbacks. |
| OpenSBI | Bounded SBI extension-list writes to the caller's buffer. Added a redzone regression test. |
| Google / Kafel | Corrected the m68k mseal argument name from size to flags. A small fix to the syscall policy definitions. |
When a MsQuic receive batch splits, the current packet's header-protection sample needs to move to offset zero for the next batch. The copy had its source and destination reversed. This is the buffer change behind the fix:
Illustrative byte values; each sample is 16 bytes. Still frame · Animation source
A few more details behind the patches
- AMDGPU: TFE/LWE image loads return an extra status word. The merge path didn't preserve it, and checking only the first instruction missed the ordinary-load to status-load ordering. The fix excludes these instructions while collecting merge candidates.
- Trezor Firmware: When a task is killed, pending message queues retained dangling pointers to dead task contexts. The fix drains and de-registers the IPC channel on task exit.
- gnark-crypto: KZG multi-proof verifiers dividing by polynomial degree panicked when given zero digests. The check returns a structured error before evaluating quotient commitments.
- OpenSBI: Advancing a buffer offset by a name's nominal length could make the remaining capacity negative, then turn it into a large unsigned size for
sbi_snprintf. The fix stops appending before the next name exceeds capacity; the test checks a redzone beyond a 16-byte buffer. - secp256k1: Functional signing tests and constant-time tests exercise different properties. The added CHECKMEM coverage reaches the custom signing entry point and nonce callback with secret-key material marked undefined, so Valgrind can catch its use in branches or memory addresses.
Active work spans cryptographic batching, zkVM curve invariants, consensus script interpretation, and transport protocol state machines.
Active patches and review threads
Status as of October 2026. Links point directly to upstream review threads.
| Project | What it's for |
|---|---|
| Bitpeek | Inspect bytes, file structures, endianness, limb schedules, and binary diffs. Runs in the browser, CLI, and as a local MCP server. Try it. |
| ecc-audit-engine | Compare secp256k1 implementations against reference mathematical models, synthesize limb bounds, and replay failing edge seeds. |
| why-ui | Let coding agents inspect actual browser behavior: find what covers a button, trace it to local source, and verify fixes live. |
I also maintain a routing simulation comparing a bandit-based router with Dijkstra across multiple seeds to track delivery rates alongside latency.


