From mboxrd@z Thu Jan 1 00:00:00 1970 Delivery-date: Thu, 09 Apr 2026 13:34:35 -0700 Received: from mail-ot1-f62.google.com ([209.85.210.62]) by mail.fairlystable.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1wAw5B-0003En-Gp for bitcoindev@gnusha.org; Thu, 09 Apr 2026 13:34:35 -0700 Received: by mail-ot1-f62.google.com with SMTP id 46e09a7af769-7dbb4f8b314sf2526293a34.3 for ; Thu, 09 Apr 2026 13:34:33 -0700 (PDT) ARC-Seal: i=3; a=rsa-sha256; t=1775766867; cv=pass; d=google.com; s=arc-20240605; b=BViXNIsaWMcBYEcFELyCpVj6M4MTjELay5BtZt+5tLx//345nAxYJx1egSE/e8QP36 dmT6QiXhSG5GfG9tkqZ/2WtcmYtZidijHHUK+R4nbTBSTzir8vv+rlKGxZb4bBlaRoLU ukMR+C80sRIuPDKxDeEgZgsHs9x1BnB+RjbjLcmlUu13OkrT147LFXzeVdfCL5V+6kxj 0wbIuvZI8tVqeikpZDC15Xty1/XweAuxiINWJ3k3CBsRjOjTFqclXmFTYZbLazAabPUC 479YDlGLgPl6s9yPuplkHKhGDX/vivdgG6Y4gdQ2heZ1dhuBQDWyzNPp5koNQkn88xQe myKQ== ARC-Message-Signature: i=3; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:to:subject:message-id:date:from :in-reply-to:references:mime-version:sender:dkim-signature :dkim-signature; bh=b0UgOt5ZbZYclg8R1Bj0PsqnBZbutbDdnO+RKJ76zJI=; fh=TijFH6JPdHapmNqWY7GNarAUizpmZYEXRgMahcYjsl4=; b=ImiDknqLf6xDXoVTYiExrdj1dx3Da/bsIJK8K/cWwwimLUcKGR91DQBfle/wK2EDyB /fWxr1+pU2CtED41lDTpH6erat/lFb3F2YJBfhVaYgRDVeflAQfn7k+dBZYRhrVHI0sT OdSjPPeGPmjl017XOhDAnCgUhwrCq1W0PmF97goMTEe8n7zOjx2akw8MveNPqWAc3xwD QX5GBbUSGxULpDsaP5L/n1UD8siQj2JqYZ5DclFxFM/v/OjaH2oGVmh4t0Mr70jmMnRz Rpc2LHUjczkroqPqXfXfpzQYV/KRYH6PepNdNh4sGtzVOYC4VOT56jSe4syd3deyLbzX XMiw==; darn=gnusha.org ARC-Authentication-Results: i=3; gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20251104 header.b="i+7w2Qf/"; arc=pass (i=1); spf=pass (google.com: domain of laolu32@gmail.com designates 2607:f8b0:4864:20::b12b as permitted sender) smtp.mailfrom=laolu32@gmail.com; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com; dara=pass header.i=@googlegroups.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20251104; t=1775766867; x=1776371667; darn=gnusha.org; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:x-original-authentication-results :x-original-sender:to:subject:message-id:date:from:in-reply-to :references:mime-version:sender:from:to:cc:subject:date:message-id :reply-to; bh=b0UgOt5ZbZYclg8R1Bj0PsqnBZbutbDdnO+RKJ76zJI=; b=AhFh3Rya1lIC3rmPoG6AUytPLK/pgqJmhjj84wkY9L/994CNmDib7/IBITD7Ox2ImE wSPWrg1pgU9OlDY95MHbb37ZmYreGpuTjLVOG4RxDK1RXryy59aQLQZzvpSP8aHHcfOG vQ6915bh5LXJ1ZOCDAMLrlAvVnnrePJa+6cNfsrIM9H6+DeJSjAGEYEc7opVlDFYELdn MSnI+5a/ZY6CUiMlLWSOhYiyrRHIeHvV9ShI0rxS+wFXQMxS74VSyGnu2KIvkS10g08h VVpR9WHjewnk962wrMC1TzG3Vm3WyQzAbQ6AcfcfALN96JVsb1axIyTHraOzRPuNOrUD xb4w== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775766867; x=1776371667; darn=gnusha.org; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:x-original-authentication-results :x-original-sender:to:subject:message-id:date:from:in-reply-to :references:mime-version:from:to:cc:subject:date:message-id:reply-to; bh=b0UgOt5ZbZYclg8R1Bj0PsqnBZbutbDdnO+RKJ76zJI=; b=l/UOEjoyYNEBkey1Ye34S3PzJY16YbY6nzMIDa5dQWTfutLRw856/nq63U0JT9dnjs iqFbcGiyRpBTpQ4/336jz+JdTHQF+MrANvwE6rT+63NBiFwBDOeXUw34XgI7A3EelnlN vGDSyggdSb4ycpEUrWxWJqGKFP6UEk47cuYhIGJAEUqKLIpytDEINUjmVdvLoUpd3oM5 ox7dVNGvblFNPJckw+BwSQGMcq9FrWJ3SdHhQweOCYaTfHta5Cuzr7+pWDVhtjTpmEcE JY/gP5dyi0u0fZc+qA7KPPX1lXgF2c4BguXmEX7ckYhTcGTy5x6hcRJ07BRHq8AVGFtX Gf5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775766867; x=1776371667; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:x-original-authentication-results :x-original-sender:to:subject:message-id:date:from:in-reply-to :references:mime-version:x-gm-gg:x-beenthere:x-gm-message-state :sender:from:to:cc:subject:date:message-id:reply-to; bh=b0UgOt5ZbZYclg8R1Bj0PsqnBZbutbDdnO+RKJ76zJI=; b=iG2uKKRsxmNrdH3gNwUV1lwAqwBvGGw5H0E1RujKkHbYYNlCqNQErAGAfzxJdgkiAL otFe6K1+oPrZxQcO577rFRuGEcWUxG41h5xczvkDdM8biGqpiHZ6G6gMvg8v9g+I2VD9 ahjG8Kk4063rZyYKcvdsXSiRycw0/a4vsJ4zH5l2eP16BGF9b5vFPzK95z9x8iA1bbO9 mitn8w9HexOLSC7wDp1uNDBpHO334qh3D2KAkXJRobYU6W3wnkxZo4S0agkmFEvh+ci7 phCu/bGjda68nErv5e7uDQ/sfUZviH07r40UbfMSQ5Y96LS43MBoE7Zm/PMAUf+H7crf /ElQ== Sender: bitcoindev@googlegroups.com X-Forwarded-Encrypted: i=3; AJvYcCXumyj/o1NZtspKxom/r178RRWxmT3DNxnNm0styCE71crRcEMWJ06wgujwQWxTCYCR6MmmPISFgtkN@gnusha.org X-Gm-Message-State: AOJu0YwBmI6FBfG/ZLBJ6Egliql+rHvvVFKf1na0V661W7cZHOXRwWeo yfgLVPnLnFWp5wH9ZO+s2kPMAkHZCB9QJ9MauPXem6wFEuAFaUPJWa5q X-Received: by 2002:a05:6820:4388:b0:67d:e836:2e46 with SMTP id 006d021491bc7-68be85d8243mr237325eaf.45.1775766867330; Thu, 09 Apr 2026 13:34:27 -0700 (PDT) X-BeenThere: bitcoindev@googlegroups.com; h="AYAyTiLHOZNhiiFGSPeid0fzmChw5Y/bXfKSBRzsauxq23WrPA==" Received: by 2002:a05:6870:d441:b0:422:f32a:6626 with SMTP id 586e51a60fabf-423dd99bcfcls109235fac.2.-pod-prod-09-us; Thu, 09 Apr 2026 13:34:23 -0700 (PDT) X-Received: by 2002:a05:6808:c2d9:b0:467:14c7:a8b5 with SMTP id 5614622812f47-4789d94c68emr399845b6e.10.1775766862925; Thu, 09 Apr 2026 13:34:22 -0700 (PDT) Received: by 2002:a05:6808:6691:20b0:467:52e4:df4a with SMTP id 5614622812f47-4775b712654msb6e; Thu, 9 Apr 2026 13:33:32 -0700 (PDT) X-Received: by 2002:a17:902:7598:b0:2b2:4ffc:a7c4 with SMTP id d9443c01a7336-2b2d5a348damr2614065ad.24.1775766811470; Thu, 09 Apr 2026 13:33:31 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1775766811; cv=pass; d=google.com; s=arc-20240605; b=AL6X6E6jb2sw13gJ3gnzDE17BCTPy294oCby8Tb2YM7E7eFQ5vM+6G3QV87lU1/2A5 VgV/xM4Dujzexyd1udG5YX3LMbmZKcjn/rO2QXqbrr9rzahdlhDjDEUtx3bDy7DXBjQ/ UJOYWe/xIedKoWmAOXFt5gItVnn2QLTWTWKsTEwc4AUfdwCwSOPT64ZqRYBsDrcuXXNt LEvBjyL84WUhu4I/oKlxSwuRp7acc3RGYV91xGCV1swuv32aAdnRRClwE2kn7Iay68AL +ZN+vNI/i6vuJgkA6MrHWEHTc0AlJUsboCjBJwnf4DQvieKPhCON9VJ6DpBJwWYnIzvw NsoQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :dkim-signature; bh=719MOsl6RFsnQiGFCa3CBPai2un8IszBmdGglP0S+eE=; fh=DMP0F9ULS1guKiqimntQRCN8ZraraesEgQuVcn7F0Z0=; b=VBQCQSdesS9KXOHDBJZbA7NLyc0M5HV4WuWjpoO2VDjl+wqwFGEJIoGCWNXXeiYoUw g47TQEvXDq5DK9w5M/gzNg5VV+Of+fWlcCf+UfNjp5k+RLtp8aeU8b1JgcF/1DwOaSrp e+wWPT+BLWKRvqOZUIAIXVZTY/wyF5Bc8/GPpZ5MTWhh1MeJHSMtH8ussx3AJR0aCLPM XUFnb/rgfOcUGYEhGJcb/U+Pjr8IClccVyMEXDlQ80KSmS5bxUwYZViNBE3wts/k6n07 IGBP0NYtH0v/mawkwnxyAeXc1o1qaVNkBOTpBvHSzBHfMod1he+6tu4+qpEUUEMl8vol ZD4g==; dara=google.com ARC-Authentication-Results: i=2; gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20251104 header.b="i+7w2Qf/"; arc=pass (i=1); spf=pass (google.com: domain of laolu32@gmail.com designates 2607:f8b0:4864:20::b12b as permitted sender) smtp.mailfrom=laolu32@gmail.com; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com; dara=pass header.i=@googlegroups.com Received: from mail-yx1-xb12b.google.com (mail-yx1-xb12b.google.com. [2607:f8b0:4864:20::b12b]) by gmr-mx.google.com with ESMTPS id d9443c01a7336-2b2d4c8956asi254355ad.0.2026.04.09.13.33.31 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 09 Apr 2026 13:33:31 -0700 (PDT) Received-SPF: pass (google.com: domain of laolu32@gmail.com designates 2607:f8b0:4864:20::b12b as permitted sender) client-ip=2607:f8b0:4864:20::b12b; Received: by mail-yx1-xb12b.google.com with SMTP id 956f58d0204a3-6507a9303fbso1511614d50.1 for ; Thu, 09 Apr 2026 13:33:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1775766811; cv=none; d=google.com; s=arc-20240605; b=h18zRckjPUG4Kb6AoXpMxIbP8G7wAuZhYD+mzm1qFP/UfTHTLbu/nM63UMZCCoPw3I x3+Ss9EdikS4dcue3EdFp+on1Fpg+uk4qSaRlSJwW7EqjedzECaPx97NSwJ6HcmlCCBE 5LCash9oxSpVvfVEZ4nnt3jn1MsSf9gVajJxbLINC+MpwUOsrBLVA2gGe1ROBXEY15yb /BvSN7n4BmKkhPwUTrMp0BAMPQ+B4aSGHtAYUA6rjXmPHfmhZHvhsBzJ1jaPWnnh+jir jTCDObI1NveUS8nO4pa1/ojxElSkXpjfT2yTBi/+bAgePuUxqQ+4wa4vxRT5ZtkIfLFE F3+w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :dkim-signature; bh=719MOsl6RFsnQiGFCa3CBPai2un8IszBmdGglP0S+eE=; fh=DMP0F9ULS1guKiqimntQRCN8ZraraesEgQuVcn7F0Z0=; b=GFteA0MjBJUancBEKEEI06JSfgiTDWi38lGAP6icmBPlYjYHmBN0DnnfaeaZzwags8 U13gCjbh2zN+SYrysAOb0YW0HxNMOILCo1HnH9J7JUJlj8S//wxkDgtUUlHsrCYgb4/p GiZxfJjGYLijj5fLUfiYIu+tUwLn8Rfz4QAxTEGxLgbjZA9uhVJQ0hx+ge4TSg50pz5l BG1x6vySjiIQpjkDcO3AxaxbvHkTAMolIu85N9+7E4Niv4ZeQ1Fndk7TUirpAmp+l3D1 SgWsjFvP6g/DTsbEncsv9Z4WrwmROnnJxSkAqS8/vSMFqX1x4yFCH+6Y7h1PsEH5oMSQ +/Yw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; arc=none X-Gm-Gg: AeBDiesppZgrj/rotmJO+NSSium61c8A7KI157BDPXz50CKp9Fdg18BQLvvxQ21Ga2+ xvJaZ+vQ1uBltlUlmWilchKT/Wk3Wv12dwCOu1JOQ2hMzxpd2PpnHoVcZUU2mQYO13lEAezgsr2 hb77NBG75+1IzTgGqVM42dc+WPG7Zs6puGtPFRxZlLy758nuDKC+GDi/Ew/t9zr+xSzfOqMDZMd DgMVPDHMr3JPPkccePuJUf19xlU7SGzCwWr5v5HdKEr6xKbwWWMLbJ2Zol5vuriLES8gk9ZDdOX cGmC0kFSlWSwcIRyV78tBqAANlFFcsa6INn/C8ZL X-Received: by 2002:a53:b174:0:b0:650:8923:5618 with SMTP id 956f58d0204a3-65198bd4155mr316153d50.57.1775766810626; Thu, 09 Apr 2026 13:33:30 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Olaoluwa Osuntokun Date: Thu, 9 Apr 2026 13:33:18 -0700 X-Gm-Features: AQROBzChUI0BQYCDjpSZTqfm7q2si3cJrdn3Pse7hdTt5g42BPd2W0M__CbjUu8 Message-ID: Subject: [bitcoindev] Re: Post-Quantum BIP-86 Recovery via zk-STARK Proof of BIP-32 Seed Knowledge To: Bitcoin Development Mailing List Content-Type: multipart/alternative; boundary="000000000000f39029064f0ced2e" X-Original-Sender: laolu32@gmail.com X-Original-Authentication-Results: gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20251104 header.b="i+7w2Qf/"; arc=pass (i=1); spf=pass (google.com: domain of laolu32@gmail.com designates 2607:f8b0:4864:20::b12b as permitted sender) smtp.mailfrom=laolu32@gmail.com; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com; dara=pass header.i=@googlegroups.com Precedence: list Mailing-list: list bitcoindev@googlegroups.com; contact bitcoindev+owners@googlegroups.com List-ID: X-Google-Group-Id: 786775582512 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , X-Spam-Score: -0.5 (/) --000000000000f39029064f0ced2e Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Thanks to Luke Childs, I was able to reduce the size of the proof from 1.8 MB, to 200 KB. The trade off is that it now takes round 180 seconds to prove vs 50 seconds. The space optimization vector here is utilizing a layer of recursion, so first the main proof is generated, then a proof that a verified would accept _that_ proof is generated. IIUC, this can be used to compress a proof a hig= h complexity into an effectively constant sized statement of proof acceptance= . Relevant commits for the curious: * https://github.com/Roasbeef/go-zkvm/compare/f691458110b6b551a20ab36d15de98d= fb6813d8c...77420055510acfc2f0bee2dcf2313365dee927e8 * https://github.com/Roasbeef/bip32-pq-zkp/compare/aae0a1a763eed6bfab8660bcfb= 8f938f91b10c10...4dcb731e4fc97f84e52c85d2768dc41612c71027 I added some sketch notes to the repo re constructing an aggregated proof via composition of a merkle tree of individual statements (would enable a singl= e proof in a block for all the statements): https://github.com/Roasbeef/bip32-pq-zkp/blob/main/docs/claim.md#future-rec= ursive-composition-sketch . -- Laolu On Tue, Apr 7, 2026 at 8:39=E2=80=AFPM Olaoluwa Osuntokun wrote: > Hi y'all, > > I found some spare time this last weekend to dust off a little side proje= ct > I started last August: extend TinyGo [1] to be able to produce RISC-V ELF > binaries capable of being run as a guest on the risc0 platform to generat= e > zk-STARK proofs of arbitrary programs. Initially, I didn't really have a > clear end target application, it was mainly a technical challenge to forc= e > me to learn a bit more about the RISC-V platform, and also the host/guest > architecture of risc0. Fast forward ~9 months later, and an initial kille= r > use case popped into my mind: a zk-STARK proof that a Taproot output publ= ic > key was generated using BIP-32, via a given BIP-86 derivation path. > > More formally: > ```math > \mathcal{R} =3D \left\lbrace\; > (\overbrace{K,\, C}^{\textsf{public}} ;\; \underbrace{s,\, > \mathbf{p}}_{\textsf{witness}}) > \;\middle|\; > \begin{aligned} > K &=3D \textsf{BIP86Taproot}\bigl(\textsf{BIP32Derive}(s,\, > \mathbf{p})\bigr) \\ > C &=3D \textsf{SHA256}\bigl(\texttt{"bip32-pq-zkp:path:v1"} \;\|\; > \mathbf{p}\bigr) > \end{aligned} > \;\right\rbrace > ``` > > where $K$ is the Taproot output key, $C$ is the path commitment, $s$ is t= he > BIP-32 seed, and $\mathbf{p}$ is the derivation path. > > > I was able to get everything working e2e over the weekend, after making > some tweaks to my initial architectural game plan! > > The TL;DR is that: > > * Given that the Taproot commitment scheme is post-quantum secure [3], = in > the future we can deploy a soft fork to _disable_ the keyspend path, > and force all Taproot spends to instead flow through the script path > (not my idea, commonly discussed amongst developers, not sure who > proposed it first). At that point, Taproot starts to resemble BIP-360= . > > * That works for script path spends, but then leaves all the BIP-86 > wallets in a bad position, as they generated outputs that provably > don't commit to a script path at all. > > * A 2023 paper (Protecting Quantum Procrastinators with Signature > Lifting: A Case Study in Cryptocurrencies [4]) proposed a solution to > this, > namely _seed lifting_ (use BIP-32 as the one-way function to the > Picnic PQ Signature scheme) to provide a post-quantum proof of secret > information a quantum attacker wouldn't be able to easily obtain. > > * The downside of that is that it reveals the secret BIP 32 seed, > exposing other non migrated UTXOs of a user. > > * With this project I've cobbled together a series of projects to be ab= le > to generate a zk-STARK proof that a Taproot output public key was > generated via BIP-32 invocation of a BIP-86 derivation path. > > * In the future a variant of this scheme can be used to enable wallets > that generated the private keys via BIP-86, to have a post quantum sa= fe > exit path in case they don't bother moving their coins in time to the > yet-to-be-decided post quantum signature scheme. > > To achieve this end, I needed to create/fork a series of repos: > > * tinygo-zkvm: https://github.com/Roasbeef/tinygo-zkvm > * A fork of TinyGo that supports the flavor of RISC-V (rv32im) that > risc0 requires to generate/execute a guest program to later be prov= ed > by the host. > > * risc0: https://github.com/Roasbeef/risc0 > * Mostly a bug fix to their c-guest example, along with some > additional documentation on how to get things running. The repo is > unmodified other than that. Recent updates to the repo made the > entire process much easier (Go guest+host), more on that later. > > * go-zkvm: https://github.com/Roasbeef/go-zkvm > * Go utilities to take a RISC-V ELf binary produced by tinygo-zkvm, a= nd > package it in the expected R0BF format, which combines the user > generated RISC-V ELF (the thing that is executed to generate the > proof) along with the v1compat ELF kernel, which is risc0's executi= on > environment. > > * This also includes a Go host package, which loads the guest program= , > executes it, and generates a trace to later be proved. This is > achieved via a C FFI compat layer between Go and the original Rust > host/proving/verification code. > > * bip-32-pq-zkp: https://github.com/Roasbeef/bip32-pq-zkp > * The project that packages everything together, this contains the: > * Guest Go program that defines the secret witness and > claim/constraints of the proof. > > * The C FFI wrapper around the OG Rust host, which is used to load > the guest program, execute it, generate a trace, then finally > generate a proof. > > Details of the final proof as generated on my Mac Book (Apple Silicon M4 > Max, 128 GB of RAM): > * Takes ~55 seconds or so to generate+proof, including execution. This > uses Metal for GPU acceleration on the platform. > * Uses ~12 GB of ram. > * Final proof size is ~1.7 MB. > * Verification takes ~1.8 seconds, and uses ~32 MB of memory. > > On several layers, this demo is far from optimized (more on that later), > this is meant to serve as a PoC to demonstrate that with the latest > software+hardware, a proof of this complexity is well within reach. > > For those curious re the e2e details I've generated this tutorial that > explains the entire system top to bottom: > https://github.com/Roasbeef/go-zkvm/blob/main/docs/tutorial.md. > > If you got to this point in this mail, and don't care about the lower lev= el > details, thanks for reading up until now, and feel free to return back to > the _The Net of a Million Lies_, or as better known in our Universe: > Monitoring the Situation and/or slopfotainment! =F0=9F=AB=A1 > > ## Motivation + Background > > As commonly known, in the case of an adversary that possesses a quantum > computer capable of breaking classical asymmetric cryptography, any coins > stored in UTXOs with a known public key are vulnerable. This is the case > for any P2PK outputs from waaaay back, and also any other outputs that ha= ve > revealed their public key. Pubkey reveal might happen due to address re-u= se > (spending from the same script twice), or Taproot outputs, which publish > the public key plainly in the pkScript. > > As detailed in [3], for Taproot outputs, a widely circulated plan is > roughly to: disable the _keyspend_ path (requires a simple signature), > enforcing a new rule that all Taproot spends must then flow through the > script path. Spending via the script path requires an opening of the > Taproot commitment (C =3D I + H(I || H(M))), which was shown to be bindin= g > even > under classic assumptions, as H(M) (tapscript merkle root) is still a > collision-resistant function. > > That means any UTXO that _does_ commit to a script path has a future esca= pe > hatch _if_ such a softfork would need to be deployed in the future. > However, what about all the other wallets that use BIP 86, and don't comm= it > to a script path at all? Under a strict version of this existing > proposal, those wallets would basically be locked forever. > > The goal of this work is to demonstrate a practical solution (discussed > against devs, but never implemented AFAICT): generate a zk proof that an > output was generated using BIP-86. For the zk-Proof, we select zk-STARKs, > as they're plausibly post quantum since they rely only on symmetric > cryptography: layers of merkle trees over an execution trace, along with > some novel sampling/error-correction algorithms. > > At this point, you may be asking: "if the quantum adversary can derive th= e > private key to a random taproot public key, then how exactly does this > help?". The answer lies in the structure of BIP-32! BIP-32 takes an initi= al > 128-512-bit seed (with BIP-39, either 12 or 24 words), then runs it throu= gh > HMAC-SHA512 keyed by "Bitcoin seed" to produce the master extended privat= e > key. An adversary who wants to forge this proof needs to find a _collidin= g_ > seed: a different seed s' such that HMAC-SHA512("Bitcoin seed", s') > produces > the same master key. The BHT algorithm (Brassard-Hoyer-Tapp [6]) is the > best known quantum collision finder, and it runs in time proportional to > the > cube root of the output space: 2^(n/3). For HMAC-SHA512's 512-bit output, > that's ~2^171 quantum operations, well above even NIST's highest > post-quantum security category. Therefore, if you generated a wallet usin= g > BIP-32, you possess _another_ secret that a quantum adversary can't > efficiently reconstruct! > > This demo focuses on the Taproot case, but the rough approach also applie= s > to any other output generated via BIP-32. BIP 32 was originally published > in > 2012, over 14 years ago. So safe to say that _most_ wallets were generate= d > under this scheme. However, Bitcoin Core only officially adopted BIP-32 i= n > 2016/2018, moving away from their existing key pool structure. I can't sa= y > how much BTC is held today in outputs generated with Bitcoin Core's > original > key pool, but if you have coins generated via that mechanism, you may wan= t > to consider migrating them to a BIP-32 wallet. > > ## TinyGo + RISC-V + risc0 > > Now for some of the lower level details. risc0 is a STARK based proving > system that takes a RISC-V ELF binary generated by a guest program (any > program generating using their flavor of rv32im can be proved), executes > that in a host environment, generates a trace, then produces a STARK proo= f > from that. > > Today you can take some subset of Rust, compile it to an ELF using their > toolchain, then execute it, generate a trace, to finally prove+verify it > using their system. > > This demo took a bit of a round about journey to achieve this, as after > all, the journey is most of the fun, ain't it! > > For the past 10 years or so, my Bitcoin stack of choice (lnd/btcsuite) us= es > a series of Go libraries, so I wanted to be able to re-use them, first fo= r > this demo, then also in the future for other projects. > > TinyGo is a special Go compiler based on LLVM, that targets mostly embedd= ed > environments. You can use it to generate go programs that can run on > micro controllers, or on web assembly (producing a smaller binary than if > you used the normal stdlib path). > > TinyGo supports RISC-V, but _not_ the 32-bit variant of RISC-V that risc0 > relies on. So the first step here was to create a new target definition f= or > TinyGo: riscv32-unknown-none, which uses base integer + multiply/divide > instructions with no compressed instructions, which uses 4 KB stacks for > each task. From there, I created a new linker script > (`targets/riscv32im-risc0-zkvm-elf.ld`) which created a memory layer > identical to what risc0 expects. The final component was a new runtime > (`src/runtime/runtime_zkvm.go`), which implemented a few platform specifi= c > syscalls for risc0 (putchar(), exit(), ticks(), and growHeap()). > > When I tried to get this working last year, I had to also implement a > number > of kernel syscalls (called ecalls in the platform [7]) to handle: > read+write > to stdin/stdout, halting, and the journaling mechanism (the transcript of > execution committed to), which basically implement the kernel that the > guest > executes in. Fast forward to 2026, and after pulling the latest version o= f > the repo, I realized that they now make a libzkvm_platform.a, which > packages > up the kernel nicely to be linked against. So I threw out my custom kerne= l > code, and slotted that in instead. > > The final component is a C FFI layer that enables me to use _both_ a Go > guest (the program to be proved) and a Go host (the thing that executes t= he > program and generates the final proof). > > ## BIP-32+Taproot zk-STARK Proof > > With basic proofs working (like the classic: I know the factorization of = a > number `n`), I was unblocked to generate the actual proof. The claim/proo= f > is represented with the following JSON artifact: > ``` > { > "schema_version": 1, > "image_id": > "8a6a2c27dd54d8fa0f99a332b57cb105f88472d977c84bfac077cbe70907a690", > "claim_version": 1, > "claim_flags": 1, > "require_bip86": true, > "taproot_output_key": > "00324bf6fa47a8d70cb5519957dd54a02b385c0ead8e4f92f9f07f992b288ee6", > "path_commitment": > "4c7de33d397de2c231e7c2a7f53e5b581ee3c20073ea79ee4afaab56de11f74b", > "journal_hex": > "010000000100000000324bf6fa47a8d70cb5519957dd54a02b385c0ead8e4f92f9f07f99= 2b288ee64c7de33d397de2c231e7c2a7f53e5b581ee3c20073ea79ee4afaab56de11f74b", > "journal_size_bytes": 72, > "proof_seal_bytes": 1797880, > "receipt_encoding": "borsh" > } > ```` > > The `image_id` is basically a hash of the ELF, so you know what the prove= r > executed. There are then a few flags that control the claim version and > whether BIP-86 derivation is a part of the proof. BIP-86 was only adopted > post-Taproot, so if you have an existing BIP-44 path, you can instead opt > to > claim that instead. The Taproot key we're generating the proof against is > also part of the _public data_, as it sits plainly on the chain for all t= o > see. We then also include a `path_commitment`, which is a commitment to t= he > exact BIP 86 path that the prover used. Finally, we also commit to the > journal hex, which is basically a commitment to the public claim. > > Assuming you've built the project, then you can generate the proof (even > passing in an arbitrary BIP-32 seed and derivation path with) > ``` > make prove GO_GOROOT=3D/path/to/go1.24.4 > ``` > > Then verify it with: > ``` > make verify GO_GOROOT=3D/path/to/go1.24.4 > ``` > > The default prove target writes: > * ./artifacts/bip32-test-vector.receipt > * ./artifacts/bip32-test-vector.claim.json > > The receipt is the STARK proof artifact. claim.json is the stable, > human-readable description of the public statement being proved. > > ## Application to a Future Keyspend Disabling Soft fork > > As mentioned above, assuming the community is forced to deploy a keyspend > disabling soft fork in the future, we can also deploy some variant of > this proof to enable both BIP-86 wallets, and also any BIP-32 wallet, to > sweep their funds into a new PQ output. > > In 2026, we've shown that this is achievable using 2 year old consumer > hardware. I don't doubt that the upcoming advancements (eg: photonics, ne= w > flavor of high bandwidth memory, etc) in hardware (driven by the fierce A= I > race) will make such a proof even more feasible. > > One thing to note is that this proof has a few layers of indirection, > mainly the RISC-V layer that adds overhead which increase the total amoun= t > of steps, and therefore the size of the proof. A production grade > deployment would likely instead hand roll a custom STARK proof for this > exact statement, to achieve a faster and smaller proof). > > # Future Work > > In terms of future work, there're a number of interesting following up > projects that can be pursued from here. > > One basic one is that the current proof doesn't actually commit to a > spending txid and/or sighash. That can be trivially incorporated into the > proof. Going a step further, the execution of the guest program can even > _generate_ a valid schnorr signature to permit spending. > > Looking to the memory+computational requirements necessary to generate th= e > proof, I've left two low hanging fruits: > > 1. First, we can speed up the Elliptic Curve operations the proof requir= es > (scalar base mult, then addition, or more performantly Double Scalar > Multiplication via the Strauss-Shamir trick). For this we can use the > syscalls/precompile in the risc0 env for big integer arithmetic: > sys_bigint and sys_bigint2. With this, the guest calls into the kerne= l > to use an optimized/accelerated circuit for the modular arithmetic, > reducing cycles, steps, and thus proof size. > > 2. Second right now, the entire claim is a single proof. Instead, we can > first break that up using their recursive proof/composition syscalls: > sys_verify_integrity+sys_verify_integrity2. We can then assembled a > series of these proofs into a _single_ statement, which can save bloc= k > space by aggregating N proofs into a single proof. > > -- Laolu > > [1]: https://tinygo.org/ > > [2]: https://risczero.com/ > > [3]: https://eprint.iacr.org/2025/1307 > > [4]: https://eprint.iacr.org/2023/362 > > [5]: https://microsoft.github.io/Picnic/ > > [6]: https://en.wikipedia.org/wiki/BHT_algorithm > > [7]: https://github.com/Roasbeef/go-zkvm/blob/main/docs/ecall-reference.m= d > > --=20 You received this message because you are subscribed to the Google Groups "= Bitcoin Development Mailing List" group. To unsubscribe from this group and stop receiving emails from it, send an e= mail to bitcoindev+unsubscribe@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/= CAO3Pvs8c1T-5aYqHGp3mc3Mt1TxMBCKzxorBAx3eVpyk0awqUg%40mail.gmail.com. --000000000000f39029064f0ced2e Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Thanks to Luke Childs, I was able to reduce the size = of the proof from 1.8 MB,
to 200 KB. The trade off is that it now takes = round 180 seconds to prove vs 50
seconds. The space optimization vector = here is utilizing a layer of recursion,
so first the main proof is gener= ated, then a proof that a verified would accept
_that_ proof is generate= d. IIUC, this can be used to compress a proof a high
complexity into an = effectively constant sized statement of proof acceptance.

Relevant c= ommits for the curious:
=C2=A0 * https://github.com/Roasbeef/go-zkvm/compare/f6914= 58110b6b551a20ab36d15de98dfb6813d8c...77420055510acfc2f0bee2dcf2313365dee92= 7e8
=C2=A0 * https://github.com/Roasbeef/bip32-pq-zkp/compare/aae0a1a763e= ed6bfab8660bcfb8f938f91b10c10...4dcb731e4fc97f84e52c85d2768dc41612c71027


I added some sketch notes to the repo re constructing an aggre= gated proof via
composition of a merkle tree of individual statements (w= ould enable a single
proof in a block for all the statements):
https://github.com/Roasbeef/bip32-pq-zkp/bl= ob/main/docs/claim.md#future-recursive-composition-sketch.

-- La= olu

On Tue, Apr 7, 2026 at 8:39=E2=80=AFPM O= laoluwa Osuntokun <laolu32@gmail.co= m> wrote:
Hi y'all,

I = found some spare time this last weekend to dust off a little side projectI started last August: extend TinyGo [1] to be able to produce RISC-V ELF=
binaries capable of being run as a guest on the risc0 platform to gener= ate
zk-STARK proofs of arbitrary programs. Initially, I didn't reall= y have a
clear end target application, it was mainly a technical challen= ge to force
me to learn a bit more about the RISC-V platform, and also t= he host/guest
architecture of risc0. Fast forward ~9 months later, and a= n initial killer
use case popped into my mind: a zk-STARK proof that a T= aproot output public
key was generated using BIP-32, via a given BIP-86 = derivation path.

More formally:
```math
\mathcal{R} =3D \left\= lbrace\;
(\overbrace{K,\, C}^{\textsf{public}} ;\; \underbrace{s,\, \mat= hbf{p}}_{\textsf{witness}})
\;\middle|\;
\begin{aligned}
=C2=A0 K = &=3D \textsf{BIP86Taproot}\bigl(\textsf{BIP32Derive}(s,\, \mathbf{p})\b= igr) \\
=C2=A0 C &=3D \textsf{SHA256}\bigl(\texttt{"bip32-pq-zk= p:path:v1"} \;\|\; \mathbf{p}\bigr)
\end{aligned}
\;\right\rbrac= e
```

where $K$ is the Taproot output key, $C$ is the path commit= ment, $s$ is the
BIP-32 seed, and $\mathbf{p}$ is the derivation path.

I was able to get everything working e2e over the weekend, after = making
some tweaks to my initial architectural game plan!

The TL;= DR is that:

=C2=A0 * Given that the Taproot commitment scheme is pos= t-quantum secure [3], in
=C2=A0 =C2=A0 the future we can deploy a soft f= ork to _disable_ the keyspend path,
=C2=A0 =C2=A0 and force all Taproot = spends to instead flow through the script path
=C2=A0 =C2=A0 (not my ide= a, commonly discussed amongst developers, not sure who
=C2=A0 =C2=A0 pro= posed it first). At that point, Taproot starts to resemble BIP-360.

= =C2=A0 * That works for script path spends, but then leaves all the BIP-86<= br>=C2=A0 =C2=A0 wallets in a bad position, as they generated outputs that = provably
=C2=A0 =C2=A0 don't commit to a script path at all.

= =C2=A0 * A 2023 paper (Protecting Quantum Procrastinators with Signature=C2=A0 =C2=A0 Lifting: A Case Study in Cryptocurrencies [4]) proposed a so= lution to this,
=C2=A0 =C2=A0 namely _seed lifting_ (use BIP-32 as the o= ne-way function to the
=C2=A0 =C2=A0 Picnic PQ Signature scheme) to prov= ide a post-quantum proof of secret
=C2=A0 =C2=A0 information a quantum a= ttacker wouldn't be able to easily obtain.

=C2=A0 * The downside= of that is that it reveals the secret BIP 32 seed,
=C2=A0 =C2=A0 exposi= ng other non migrated UTXOs of a user.

=C2=A0 * With this project I&= #39;ve cobbled together a series of projects to be able
=C2=A0 =C2=A0 to= generate a zk-STARK proof that a Taproot output public key was
=C2=A0 = =C2=A0 generated via BIP-32 invocation of a BIP-86 derivation path.

= =C2=A0 * In the future a variant of this scheme can be used to enable walle= ts
=C2=A0 =C2=A0 that generated the private keys via BIP-86, to have a p= ost quantum safe
=C2=A0 =C2=A0 exit path in case they don't bother m= oving their coins in time to the
=C2=A0 =C2=A0 yet-to-be-decided post qu= antum signature scheme.

To achieve this end, I needed to create/fork= a series of repos:

=C2=A0 * tinygo-zkvm: https://github.com/Roasbeef/tin= ygo-zkvm
=C2=A0 =C2=A0 * A fork of TinyGo that supports the flavor o= f RISC-V (rv32im) that
=C2=A0 =C2=A0 =C2=A0 risc0 requires to generate/e= xecute a guest program to later be proved
=C2=A0 =C2=A0 =C2=A0 by the ho= st.

=C2=A0 * risc0: https://github.com/Roasbeef/risc0
=C2=A0 =C2=A0 * Mo= stly a bug fix to their c-guest example, along with some
=C2=A0 =C2=A0 = =C2=A0 additional documentation on how to get things running. The repo is=C2=A0 =C2=A0 =C2=A0 unmodified other than that. Recent updates to the re= po made the
=C2=A0 =C2=A0 =C2=A0 entire process much easier (Go guest+ho= st), more on that later.

=C2=A0 * go-zkvm: https://github.com/Roasbeef/go-zkv= m
=C2=A0 =C2=A0 * Go utilities to take a RISC-V ELf binary produced = by tinygo-zkvm, and
=C2=A0 =C2=A0 =C2=A0 package it in the expected R0BF= format, which combines the user
=C2=A0 =C2=A0 =C2=A0 generated RISC-V E= LF (the thing that is executed to generate the
=C2=A0 =C2=A0 =C2=A0 proo= f) along with the v1compat ELF kernel, which is risc0's execution
= =C2=A0 =C2=A0 =C2=A0 environment.

=C2=A0 =C2=A0 * This also includes= a Go host package, which loads the guest program,
=C2=A0 =C2=A0 =C2=A0 = executes it, and generates a trace to later be proved. This is
=C2=A0 = =C2=A0 =C2=A0 achieved via a C FFI compat layer between Go and the original= Rust
=C2=A0 =C2=A0 =C2=A0 host/proving/verification code.

=C2=A0= * bip-32-pq-zkp: https://github.com/Roasbeef/bip32-pq-zkp
=C2=A0 =C2=A0= * The project that packages everything together, this contains the:
=C2= =A0 =C2=A0 =C2=A0 * Guest Go program that defines the secret witness and=C2=A0 =C2=A0 =C2=A0 =C2=A0 claim/constraints of the proof.

=C2=A0 = =C2=A0 =C2=A0 * The C FFI wrapper around the OG Rust host, which is used to= load
=C2=A0 =C2=A0 =C2=A0 =C2=A0 the guest program, execute it, generat= e a trace, then finally
=C2=A0 =C2=A0 =C2=A0 =C2=A0 generate a proof.
Details of the final proof as generated on my Mac Book (Apple Silicon = M4
Max, 128 GB of RAM):
=C2=A0 * Takes ~55 seconds or so to generate+= proof, including execution. This
=C2=A0 =C2=A0 uses Metal for GPU accele= ration on the platform.
=C2=A0 * Uses ~12 GB of ram.
=C2=A0 * Final p= roof size is ~1.7 MB.
=C2=A0 * Verification takes ~1.8 seconds, and uses= ~32 MB of memory.

On several layers, this demo is far from optimize= d (more on that later),
this is meant to serve as a PoC to demonstrate t= hat with the latest
software+hardware, a proof of this complexity is wel= l within reach.

For those curious re the e2e details I've genera= ted this tutorial that
explains the entire system top to bottom:
https://github.com/Roasbeef/go-zkvm/blob/main/docs/tutorial.m= d.

If you got to this point in this mail, and don't care abo= ut the lower level
details, thanks for reading up until now, and feel fr= ee to return back to
the _The Net of a Million Lies_, or as better known= in our Universe:
Monitoring the Situation and/or slopfotainment! =F0=9F= =AB=A1

## Motivation + Background

As commonly known, in the c= ase of an adversary that possesses a quantum
computer capable of breakin= g classical asymmetric cryptography, any coins
stored in UTXOs with a kn= own public key are vulnerable. This is the case
for any P2PK outputs fro= m waaaay back, and also any other outputs that have
revealed their publi= c key. Pubkey reveal might happen due to address re-use
(spending from t= he same script twice), or Taproot outputs, which publish
the public key = plainly in the pkScript.

As detailed in [3], for Taproot outputs, a = widely circulated plan is
roughly to: disable the _keyspend_ path (requi= res a simple signature),
enforcing a new rule that all Taproot spends mu= st then flow through the
script path. Spending via the script path requi= res an opening of the
Taproot commitment (C =3D I + H(I || H(M))), which= was shown to be binding even
under classic assumptions, as H(M) (tapscr= ipt merkle root) is still a
collision-resistant function.

That me= ans any UTXO that _does_ commit to a script path has a future escape
hat= ch _if_ such a softfork would need to be deployed in the future.
However= , what about all the other wallets that use BIP 86, and don't committo a script path at all? Under a strict version of this existing
propos= al, those wallets would basically be locked forever.

The goal of thi= s work is to demonstrate a practical solution (discussed
against devs, b= ut never implemented AFAICT): generate a zk proof that an
output was gen= erated using BIP-86. For the zk-Proof, we select zk-STARKs,
as they'= re plausibly post quantum since they rely only on symmetric
cryptography= : layers of merkle trees over an execution trace, along with
some novel = sampling/error-correction algorithms.

At this point, you may be aski= ng: "if the quantum adversary can derive the
private key to a rando= m taproot public key, then how exactly does this
help?". The answer= lies in the structure of BIP-32! BIP-32 takes an initial
128-512-bit se= ed (with BIP-39, either 12 or 24 words), then runs it through
HMAC-SHA51= 2 keyed by "Bitcoin seed" to produce the master extended private<= br>key. An adversary who wants to forge this proof needs to find a _collidi= ng_
seed: a different seed s' such that HMAC-SHA512("Bitcoin se= ed", s') produces
the same master key. The BHT algorithm (Brass= ard-Hoyer-Tapp [6]) is the
best known quantum collision finder, and it r= uns in time proportional to the
cube root of the output space: 2^(n/3). = For HMAC-SHA512's 512-bit output,
that's ~2^171 quantum operatio= ns, well above even NIST's highest
post-quantum security category. T= herefore, if you generated a wallet using
BIP-32, you possess _another_ = secret that a quantum adversary can't
efficiently reconstruct!
This demo focuses on the Taproot case, but the rough approach also applie= s
to any other output generated via BIP-32. BIP 32 was originally publis= hed in
2012, over 14 years ago. So safe to say that _most_ wallets were = generated
under this scheme. However, Bitcoin Core only officially adopt= ed BIP-32 in
2016/2018, moving away from their existing key pool structu= re. I can't say
how much BTC is held today in outputs generated with= Bitcoin Core's original
key pool, but if you have coins generated v= ia that mechanism, you may want
to consider migrating them to a BIP-32 w= allet.

## TinyGo + RISC-V + risc0

Now for some of the lower l= evel details. risc0 is a STARK based proving
system that takes a RISC-V = ELF binary generated by a guest program (any
program generating using th= eir flavor of rv32im can be proved), executes
that in a host environment= , generates a trace, then produces a STARK proof
from that.

Today= you can take some subset of Rust, compile it to an ELF using their
tool= chain, then execute it, generate a trace, to finally prove+verify it
usi= ng their system.

This demo took a bit of a round about journey to ac= hieve this, as after
all, the journey is most of the fun, ain't it!<= br>
For the past 10 years or so, my Bitcoin stack of choice (lnd/btcsuit= e) uses
a series of Go libraries, so I wanted to be able to re-use them,= first for
this demo, then also in the future for other projects.
TinyGo is a special Go compiler based on LLVM, that targets mostly embedde= d
environments. You can use it to generate go programs that can run onmicro controllers, or on web assembly (producing a smaller binary than if=
you used the normal stdlib path).

TinyGo supports RISC-V, but _n= ot_ the 32-bit variant of RISC-V that risc0
relies on. So the first step= here was to create a new target definition for
TinyGo: riscv32-unknown-= none, which uses base integer + multiply/divide
instructions with no com= pressed instructions, which uses 4 KB stacks for
each task. From there, = I created a new linker script
(`targets/riscv32im-risc0-zkvm-elf.ld`) wh= ich created a memory layer
identical to what risc0 expects. The final co= mponent was a new runtime
(`src/runtime/runtime_zkvm.go`), which impleme= nted a few platform specific
syscalls for risc0 (putchar(), exit(), tick= s(), and growHeap()).

When I tried to get this working last year, I = had to also implement a number
of kernel syscalls (called ecalls in the = platform [7]) to handle: read+write
to stdin/stdout, halting, and the jo= urnaling mechanism (the transcript of
execution committed to), which bas= ically implement the kernel that the guest
executes in. Fast forward to = 2026, and after pulling the latest version of
the repo, I realized that = they now make a libzkvm_platform.a, which packages
up the kernel nicely = to be linked against. So I threw out my custom kernel
code, and slotted = that in instead.

The final component is a C FFI layer that enables m= e to use _both_ a Go
guest (the program to be proved) and a Go host (the= thing that executes the
program and generates the final proof).

= ## BIP-32+Taproot zk-STARK Proof

With basic proofs working (like the= classic: I know the factorization of a
number `n`), I was unblocked to = generate the actual proof. The claim/proof
is represented with the follo= wing JSON artifact:
```
{
=C2=A0 "schema_version": 1,=C2=A0 "image_id": "8a6a2c27dd54d8fa0f99a332b57cb105f88472d= 977c84bfac077cbe70907a690",
=C2=A0 "claim_version": 1,=C2=A0 "claim_flags": 1,
=C2=A0 "require_bip86": tr= ue,
=C2=A0 "taproot_output_key": "00324bf6fa47a8d70cb5519= 957dd54a02b385c0ead8e4f92f9f07f992b288ee6",
=C2=A0 "path_commi= tment": "4c7de33d397de2c231e7c2a7f53e5b581ee3c20073ea79ee4afaab56= de11f74b",
=C2=A0 "journal_hex": "010000000100000000= 324bf6fa47a8d70cb5519957dd54a02b385c0ead8e4f92f9f07f992b288ee64c7de33d397de= 2c231e7c2a7f53e5b581ee3c20073ea79ee4afaab56de11f74b",
=C2=A0 "= journal_size_bytes": 72,
=C2=A0 "proof_seal_bytes": 17978= 80,
=C2=A0 "receipt_encoding": "borsh"
}
````<= br>
The `image_id` is basically a hash of the ELF, so you know what the = prover
executed. There are then a few flags that control the claim versi= on and
whether BIP-86 derivation is a part of the proof. BIP-86 was only= adopted
post-Taproot, so if you have an existing BIP-44 path, you can i= nstead opt to
claim that instead. The Taproot key we're generating t= he proof against is
also part of the _public data_, as it sits plainly o= n the chain for all to
see. We then also include a `path_commitment`, wh= ich is a commitment to the
exact BIP 86 path that the prover used. Final= ly, we also commit to the
journal hex, which is basically a commitment t= o the public claim.

Assuming you've built the project, then you = can generate the proof (even
passing in an arbitrary BIP-32 seed and der= ivation path with)
```
make prove GO_GOROOT=3D/path/to/go1.24.4
``= `

Then verify it with:
```
make verify GO_GOROOT=3D/path/to/go= 1.24.4
```

The default prove target writes:
=C2=A0 * ./artifac= ts/bip32-test-vector.receipt
=C2=A0 * ./artifacts/bip32-test-vector.clai= m.json

The receipt is the STARK proof artifact. claim.json is the st= able,
human-readable description of the public statement being proved.
## Application to a Future Keyspend Disabling Soft fork

As men= tioned above, assuming the community is forced to deploy a keyspend
disa= bling soft fork in the future, we can also deploy some variant of
this p= roof to enable both BIP-86 wallets, and also any BIP-32 wallet, to
sweep= their funds into a new PQ output.

In 2026, we've shown that thi= s is achievable using 2 year old consumer
hardware. I don't doubt th= at the upcoming advancements (eg: photonics, new
flavor of high bandwidt= h memory, etc) in hardware (driven by the fierce AI
race) will make such= a proof even more feasible.

One thing to note is that this proof ha= s a few layers of indirection,
mainly the RISC-V layer that adds overhea= d which increase the total amount
of steps, and therefore the size of th= e proof. A production grade
deployment would likely instead hand roll a = custom STARK proof for this
exact statement, to achieve a faster and sma= ller proof).

# Future Work

In terms of future work, there'= ;re a number of interesting following up
projects that can be pursued fr= om here.

One basic one is that the current proof doesn't actuall= y commit to a
spending txid and/or sighash. That can be trivially incorp= orated into the
proof. Going a step further, the execution of the guest = program can even
_generate_ a valid schnorr signature to permit spending= .

Looking to the memory+computational requirements necessary to gene= rate the
proof, I've left two low hanging fruits:

=C2=A01. Fi= rst, we can speed up the Elliptic Curve operations the proof requires
= =C2=A0 =C2=A0 (scalar base mult, then addition, or more performantly Double= Scalar
=C2=A0 =C2=A0 Multiplication via the Strauss-Shamir trick). For = this we can use the
=C2=A0 =C2=A0 syscalls/precompile in the risc0 env f= or big integer arithmetic:
=C2=A0 =C2=A0 sys_bigint and sys_bigint2. Wit= h this, the guest calls into the kernel
=C2=A0 =C2=A0 to use an optimize= d/accelerated circuit for the modular arithmetic,
=C2=A0 =C2=A0 reducing= cycles, steps, and thus proof size.

=C2=A02. Second right now, the = entire claim is a single proof. Instead, we can
=C2=A0 =C2=A0 first brea= k that up using their recursive proof/composition syscalls:
=C2=A0 =C2= =A0 sys_verify_integrity+sys_verify_integrity2. We can then assembled a
= =C2=A0 =C2=A0 series of these proofs into a _single_ statement, which can s= ave block
=C2=A0 =C2=A0 space by aggregating N proofs into a single proo= f.

-- Laolu

[1]: https://tinygo.org/

[2]: https://risczero.com/

[3]: https://eprint.iacr.org/2025/= 1307

[4]: https://eprint.iacr.org/2023/362

[5]: https://microsoft.github.i= o/Picnic/

[6]: https://en.wikipedia.org/wiki/BHT_algorithm
[7]: https://github.com/Roasbeef/go-zkvm/blob= /main/docs/ecall-reference.md

--
You received this message because you are subscribed to the Google Groups &= quot;Bitcoin Development Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an e= mail to bitcoind= ev+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/ms= gid/bitcoindev/CAO3Pvs8c1T-5aYqHGp3mc3Mt1TxMBCKzxorBAx3eVpyk0awqUg%40mail.g= mail.com.
--000000000000f39029064f0ced2e--