From mboxrd@z Thu Jan 1 00:00:00 1970 Delivery-date: Sat, 02 May 2026 11:09:57 -0700 Received: from mail-oa1-f57.google.com ([209.85.160.57]) by mail.fairlystable.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1wJEmq-0007RC-2U for bitcoindev@gnusha.org; Sat, 02 May 2026 11:09:57 -0700 Received: by mail-oa1-f57.google.com with SMTP id 586e51a60fabf-409037c3f0bsf4270521fac.1 for ; Sat, 02 May 2026 11:09:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20251104; t=1777745390; x=1778350190; darn=gnusha.org; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:x-original-sender:mime-version :subject:references:in-reply-to:message-id:to:from:date:sender:from :to:cc:subject:date:message-id:reply-to; bh=6JRXQF2luWBl1Sktyhe/LqPxFTUiyHD3pfCrE/2o2i0=; b=OUMNsMeY6j+pi6BVqvP2Vs85tqkPu9ZXode6Q9vkzaegioh2gNNjtJPwrghruxksAU 3TXYJIieiqKG3DDAmMI772QHR5uZEA31ZIbentgixTRHVgMkVu7SuqucwVu8T8h4CnZz GN5GCAp6xm90fxEKameaLA4HYkyiQtywsIeX9jFU43q8ckhb6dvZGexj9QDseihnGVEy UhJr0Ci5n/taWWwm4dvngDFJdI0s8nb01c3KrWsFAUJ79PEJLH1mEmb30yK7GPOS+HSr FC3nf1hCrEZHdcjUle2l6b+OvWtVnrPjsfvtalp5jCw2PlhHHXtosN8shWZJxInMdH/T Bvcw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777745390; x=1778350190; darn=gnusha.org; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:x-original-sender:mime-version :subject:references:in-reply-to:message-id:to:from:date:from:to:cc :subject:date:message-id:reply-to; bh=6JRXQF2luWBl1Sktyhe/LqPxFTUiyHD3pfCrE/2o2i0=; b=D7z8dNGHbSILmtonxukZgDps71tnJNoPuBO9dwPM25UixQnIcLnMfYevlG0ixdlK4S R3FkvrTitx6QVQ6ZXVUEKvw+4vovgGmt3+qzN40aThy7dR/zKWTQUQmBzSxAgFiYJf7P aPe9GLNw4zU/BUEUl0H9E6UmvQEWv49yLtqSTPiedXHiT+do4zDmRSYJy4Q2jL0tqZEc D6s/9epSBNIMPOBsTFgfXMgX0SkmUuCqwsRTNOQeF8UGEDo/rP8dKDUSu4OdJlKy9BeN z4LDgF6tMya0W1TU+EMkgUGBKDlaP75tzHLOem5V9VDePO7Q0/1kzOaqJAac4K0v+wd+ 5aIg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777745390; x=1778350190; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:x-original-sender:mime-version :subject:references:in-reply-to:message-id:to:from:date:x-beenthere :x-gm-message-state:sender:from:to:cc:subject:date:message-id :reply-to; bh=6JRXQF2luWBl1Sktyhe/LqPxFTUiyHD3pfCrE/2o2i0=; b=gGDd+KJhbrXhe6YQzE4Ri2SuLEM1vXShgGGoXqhb4sw06je722qRYjgFYTpuEfR6A3 LBuZDSvpw6mYTYAS524VHl0kIdXDN17/iSuNHNtaL2WUUkJcCc6fDlx3k2SbzEG3g+Yb HYlZaX6/27BM6aA0xx+RJ7E3xR+S/249OCxoxpJf8ubsohvlyIb04WpNk/hoOg5TXeN3 TITMkB+GQQGb7+NgpdiAU7O+donRnxo71hcVt8ue0pkO8O/zE9as4wgdesK7EpjMYB3C NyXJgSD62YbRsey7cL7pn74Br36RRhoHYJ8e9Cd3kKapOuxJiQ7Cmiq5EdBgC/6Y2+TJ 05Iw== Sender: bitcoindev@googlegroups.com X-Forwarded-Encrypted: i=1; AFNElJ8nUC0NipX7NE5RhdoJLCtsyxK/x+Q6iLE0CfXzDkJmldWZ0T1mZfZU+hJw2NKq14j7lQIW5VyWbh8p@gnusha.org X-Gm-Message-State: AOJu0YzSNZC7w3ImK7GbUVLaIx2Uo5zYZNIYsMMWqynxxP2775Qg5K5V 1vyGhLSQQ2L2UN33E7KuG1s+TjUA4WHS70RNZawbLJ9b/RUKNH69gWt5 X-Received: by 2002:a05:6820:160e:b0:696:6d4f:a46c with SMTP id 006d021491bc7-69697c65476mr1808223eaf.30.1777745389795; Sat, 02 May 2026 11:09:49 -0700 (PDT) X-BeenThere: bitcoindev@googlegroups.com; h="AUV6zMO1TxYseQC/gg4JUD9I7vK+5O9LnxhqmYvsuTJkM7y41A==" Received: by 2002:a05:6870:169b:b0:42c:22ed:f980 with SMTP id 586e51a60fabf-434371a384bls1535557fac.0.-pod-prod-01-us; Sat, 02 May 2026 11:09:45 -0700 (PDT) X-Received: by 2002:a05:6808:3087:b0:46a:7ab9:c339 with SMTP id 5614622812f47-47c89016a18mr1751254b6e.14.1777745385069; Sat, 02 May 2026 11:09:45 -0700 (PDT) Received: by 2002:a05:690c:a083:10b0:7b3:13f7:5f3a with SMTP id 00721157ae682-7bd76818dbams7b3; Sat, 2 May 2026 11:09:14 -0700 (PDT) X-Received: by 2002:a05:690c:92:b0:7bd:6a98:58db with SMTP id 00721157ae682-7bd76fdb523mr39001587b3.22.1777745353204; Sat, 02 May 2026 11:09:13 -0700 (PDT) Date: Sat, 2 May 2026 11:09:12 -0700 (PDT) From: jeremy To: Bitcoin Development Mailing List Message-Id: <8a82e9d6-b013-4b7f-ba9f-f91f50b1bbe3n@googlegroups.com> In-Reply-To: References: <123e5545-2eda-4eca-9532-4f4cea2b83ecn@googlegroups.com> Subject: Re: [bitcoindev] [BIP-0054] 64-Byte Transactions and Potential Legitimate Uses MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_Part_276570_1438884530.1777745352552" X-Original-Sender: Jeremy.L.Rubin@gmail.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 (/) ------=_Part_276570_1438884530.1777745352552 Content-Type: multipart/alternative; boundary="----=_Part_276571_8528284.1777745352552" ------=_Part_276571_8528284.1777745352552 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Chris, These examples should work and could be adapted to a different funding=20 input (I stubbed out the actual signature with just a preimage reveal for= =20 simplicity). funding witnessScript:=20 a820ff76f4f923cd475f27097b3822640a9b441894f3d4f742fe70e745e986da388e87=20 funding scriptPubKey:=20 002080c153db1ea3461a2b70126f853189fc34d7d9926f083dfb2bffae8ae2bb1130=20 funding txid:=20 166ef40e58f1a62e01d610023ca7935eef372cf3c1239d81430dffbd1fe8fe9e=20 funding tx hex:=20 02000000010000000000000000000000000000000000000000000000000000000000000000f= fffffff020101ffffffff01a08601000000000022002080c153db1ea3461a2b70126f853189= fc34d7d9926f083dfb2bffae8ae2bb113000000000=20 182 |=20 spending output scriptPubKey: 020002b2=20 spending stripped size: 64=20 spending full size: 114=20 spending txid:=20 44c752f499326a59a78259b455875d296108184b7f25b9a0b41bc018af7aedd8=20 spending wtxid:=20 1e6eb4de698f079cbaa0fdf47d7ab5e1bb4939fae42652f295dd05d15930074d=20 spending tx stripped hex:=20 02000000019efee81fbdff0d43819d23c1f32c37ef5e93a73c0210d6012ea6f1580ef46e160= 000000000ffffffff01905f01000000000004020002b200000000=20 spending tx full hex:=20 020000000001019efee81fbdff0d43819d23c1f32c37ef5e93a73c0210d6012ea6f1580ef46= e160000000000ffffffff01905f01000000000004020002b2020a62697035342064656d6f23= a820ff76f4f923cd475f27097b3822640a9b441894f3d4f742fe70e745e986da388e8700000= 000=20 *$ decodrawtransaction $(cat funding_tx.hex)* { "txid":=20 "166ef40e58f1a62e01d610023ca7935eef372cf3c1239d81430dffbd1fe8fe9e", "hash":=20 "166ef40e58f1a62e01d610023ca7935eef372cf3c1239d81430dffbd1fe8fe9e", "version": 2, "size": 96, "vsize": 96, "weight": 384, "locktime": 0, "vin": [ { "coinbase": "0101", "sequence": 4294967295 } ], "vout": [ { "value": 0.00100000, "n": 0, "scriptPubKey": { "asm": "0=20 80c153db1ea3461a2b70126f853189fc34d7d9926f083dfb2bffae8ae2bb1130", "desc":=20 "addr(bcrt1qsrq48kc75drp52mszfhc2vvfls6d0kvjduyrm7etl7hg4c4mzycqmw604m)#2rr= nsnlc", "hex":=20 "002080c153db1ea3461a2b70126f853189fc34d7d9926f083dfb2bffae8ae2bb1130", "address":=20 "bcrt1qsrq48kc75drp52mszfhc2vvfls6d0kvjduyrm7etl7hg4c4mzycqmw604m", "type": "witness_v0_scripthash" } } ] } *$ decodrawtransaction $(cat spending_tx_stripped.hex)* { "txid":=20 "44c752f499326a59a78259b455875d296108184b7f25b9a0b41bc018af7aedd8", "hash":=20 "44c752f499326a59a78259b455875d296108184b7f25b9a0b41bc018af7aedd8", "version": 2, "size": 64, "vsize": 64, "weight": 256, "locktime": 0, "vin": [ { "txid":=20 "166ef40e58f1a62e01d610023ca7935eef372cf3c1239d81430dffbd1fe8fe9e", "vout": 0, "scriptSig": { "asm": "", "hex": "" }, "sequence": 4294967295 } ], "vout": [ { "value": 0.00090000, "n": 0, "scriptPubKey": { "asm": "512 OP_CHECKSEQUENCEVERIFY", "desc": "raw(020002b2)#vceh5z0j", "hex": "020002b2", "type": "nonstandard" } } ] } *$ decodrawtransaction $(cat spending_tx_full.hex)* { "txid":=20 "44c752f499326a59a78259b455875d296108184b7f25b9a0b41bc018af7aedd8", "hash":=20 "1e6eb4de698f079cbaa0fdf47d7ab5e1bb4939fae42652f295dd05d15930074d", "version": 2, "size": 114, "vsize": 77, "weight": 306, "locktime": 0, "vin": [ { "txid":=20 "166ef40e58f1a62e01d610023ca7935eef372cf3c1239d81430dffbd1fe8fe9e", "vout": 0, "scriptSig": { "asm": "", "hex": "" }, "txinwitness": [ "62697035342064656d6f", =20 "a820ff76f4f923cd475f27097b3822640a9b441894f3d4f742fe70e745e986da388e87" ], "sequence": 4294967295 } ], "vout": [ { "value": 0.00090000, "n": 0, "scriptPubKey": { "asm": "512 OP_CHECKSEQUENCEVERIFY", "desc": "raw(020002b2)#vceh5z0j", "hex": "020002b2", "type": "nonstandard" } } ] } ```python3 #!/usr/bin/env python3 from __future__ import annotations import hashlib import struct OP_SHA256 =3D 0xA8 OP_EQUAL =3D 0x87 OP_CHECKSEQUENCEVERIFY =3D 0xB2 def sha256(b: bytes) -> bytes: return hashlib.sha256(b).digest() def hash256(b: bytes) -> bytes: return hashlib.sha256(hashlib.sha256(b).digest()).digest() def hash256_be_hex(b: bytes) -> str: return hash256(b)[::-1].hex() def compact_size(n: int) -> bytes: if n < 0: raise ValueError("negative compact size") if n < 253: return bytes([n]) if n <=3D 0xFFFF: return b"\xfd" + struct.pack(" bytes: return struct.pack(" bytes: return struct.pack(" bytes: return struct.pack(" bytes: return u64(value_sat) + compact_size(len(script_pubkey)) + script_pubke= y def ser_input(prev_txid_be_hex: str, vout: int, script_sig: bytes =3D b"",= =20 sequence: int =3D 0xFFFFFFFF) -> bytes: # Transaction outpoints serialize txids little-endian. prev_txid_le =3D bytes.fromhex(prev_txid_be_hex)[::-1] return ( prev_txid_le + u32(vout) + compact_size(len(script_sig)) + script_sig + u32(sequence) ) # -------------------------------------------------------------------- # Funding transaction # -------------------------------------------------------------------- # # This is a coinbase-like funding transaction for a decode/test vector. # It pays 100_000 sats to a native P2WSH output. # # witnessScript: # # OP_SHA256 OP_EQUAL # # The spending transaction must reveal the preimage "bip54 demo" in witness= . secret =3D b"bip54 demo" secret_hash =3D sha256(secret) witness_script =3D ( bytes([OP_SHA256]) + bytes([0x20]) # push 32 bytes + secret_hash + bytes([OP_EQUAL]) ) # Native v0 P2WSH scriptPubKey: # # OP_0 # funding_script_pubkey =3D b"\x00\x20" + sha256(witness_script) coinbase_script_sig =3D b"\x01\x01" # BIP34-style height=3D1 push; enough = for=20 a decode vector. funding_tx =3D ( i32(2) + compact_size(1) + bytes(32) # coinbase prevout txid =3D 0x00..00 + u32(0xFFFFFFFF) # coinbase prevout index + compact_size(len(coinbase_script_sig)) + coinbase_script_sig + u32(0xFFFFFFFF) + compact_size(1) + ser_output(100_000, funding_script_pubkey) + u32(0) ) funding_txid =3D hash256_be_hex(funding_tx) # -------------------------------------------------------------------- # Spending transaction # -------------------------------------------------------------------- # # This spends funding_tx output 0. # # The sole output scriptPubKey is: # # <512> OP_CHECKSEQUENCEVERIFY # # Minimal ScriptNum encoding for decimal 512 is little-endian 00 02, # so the full script is: # # 02 00 02 b2 # # This spending transaction has: # # witness-stripped size =3D exactly 64 bytes # full witness serialization =3D larger than 64 bytes csv512_script_pubkey =3D bytes([0x02, 0x00, 0x02, OP_CHECKSEQUENCEVERIFY]) spending_input =3D ser_input( prev_txid_be_hex=3Dfunding_txid, vout=3D0, script_sig=3Db"", sequence=3D0xFFFFFFFF, ) spending_output =3D ser_output(90_000, csv512_script_pubkey) spending_tx_stripped =3D ( i32(2) + compact_size(1) + spending_input + compact_size(1) + spending_output + u32(0) ) # P2WSH witness stack: # # # spending_witness =3D ( compact_size(2) + compact_size(len(secret)) + secret + compact_size(len(witness_script)) + witness_script ) spending_tx_full =3D ( i32(2) + b"\x00\x01" # SegWit marker + flag + compact_size(1) + spending_input + compact_size(1) + spending_output + spending_witness + u32(0) ) assert len(spending_tx_stripped) =3D=3D 64 assert csv512_script_pubkey.hex() =3D=3D "020002b2" print("funding witnessScript:", witness_script.hex()) print("funding scriptPubKey: ", funding_script_pubkey.hex()) print("funding txid: ", funding_txid) print("funding tx hex: ", funding_tx.hex()) print() print("spending output scriptPubKey:", csv512_script_pubkey.hex()) print("spending stripped size: ", len(spending_tx_stripped)) print("spending full size: ", len(spending_tx_full)) print("spending txid: ", hash256_be_hex(spending_tx_stripped)= ) print("spending wtxid: ", hash256_be_hex(spending_tx_full)) print("spending tx stripped hex: ", spending_tx_stripped.hex()) print("spending tx full hex: ", spending_tx_full.hex()) ``` On Saturday, May 2, 2026 at 8:56:25=E2=80=AFAM UTC-7 Chris Stewart wrote: > I do concede your point that witness stripping isn't well understood by= =20 > the general community. Here is a writeup I did for readers of the mailing= =20 > list that may not understand what Jeremy is talking about the=20 > characteristics of a 64 byte transaction[0]. There is a big distinction= =20 > between pre-segwit 64 byte transactions and segwit 64 byte transactions. > > > > A transaction that donates to a future miner from a segwit (any version= )=20 > output via a spend to something like <512> OP_CSV (-> push2 bytes 512 csv= =20 > -> 0x02 0x00 0x02 0xb2) > > I find this confusing. Can you give 2 hex encoded transactions (funding= =20 > transaction, spending transaction) that do this? regtest is fine, i can= =20 > just decode locally. > > Splitting hairs semantically if understand the transactions you are=20 > proposing above, "donating" to a "future miner" i.e. sending money to *an= yone=20 > (not a specific someone)* in the future that can mine a block - doesn't= =20 > seem much different to me than "anyone can spend the funds". I'll await= =20 > your transactions though in the case that I am missing something. > > [0] -=20 > https://delvingbitcoin.org/t/great-consensus-cleanup-revival/710/73?u=3Dc= hris_stewart_5 > > On Fri, May 1, 2026 at 4:15=E2=80=AFPM jeremy wrot= e: > >> For fun, let's start with a pop-quiz: >> >> Select all that apply: There can exist a transaction of ___ bytes=20 >> serialized size that BIP-0054's 64-byte restriction invalidates: >> >> A) 64 Bytes >> B) 0 Bytes >> C) 1.5MB >> D) 32 Bytes >> E) 5MB >> >> >> The answer is A, 64 Bytes, and -- perhaps surprisingly -- C, 1.5MB.=20 >> >> Why is this the case? >> >> BIP-0054 uses the term 64-byte transaction, but defines it as follows: >> >> *> Transactions whose witness-stripped serialized size is exactly 64=20 >> bytes are invalid.* >> >> In a [personally run] straw-poll of devs at a recent conference, no-one= =20 >> knew this precise edge condition or that the transactions could have a= =20 >> meaningful witness. For clarity, the restriction on bytes is on=20 >> INVALID_TX_NONWITNESS_SIZE, not on the size with Witness. >> >> Therefore, it is more accurate to refer to this in all sentences=20 >> throughout the BIP as: >> >> *> transactions with exactly 64 bytes of non-witness data*, >> >> due to the propensity for confusion. >> >> BIP-0054 also makes a comment that the transactions it invalidates are= =20 >> essentially useless: >> >> >> *> 64-byte transactions can only contain a scriptPubKey that lets anyone= =20 >> spend the funds, or one that burns them.* >> >> This is not strictly correct. Here are a few examples of current and=20 >> future uses for 64-byte transactions: >> >> *Current Uses:* >> - A transaction that donates to a future miner from a segwit (any=20 >> version) output via a spend to something like <512> OP_CSV (-> push2 byt= es=20 >> 512 csv -> 0x02 0x00 0x02 0xb2) >> - That same output which is used as a connector output for things that= =20 >> should be claimed by a miner at a future time >> - Pay-to-Anchor / ephemeral anchor outputs -- while typically p2a is for= =20 >> txns you want to add a subsidy ability, a 64-byte txn could be used to s= him=20 >> a keyed anchor to a p2a output after a certain delay. >> >> *Future Uses:* >> - Future work which might use output scripts for e.g. Transaction Sponso= r=20 >> encodings >> - Future covenants work which encodes time-of-creation run scripts that= =20 >> e.g. quine an input; possibly in conjunction with sponsors >> - Future where we have expensive reusable PQ or Contract public keys tha= t=20 >> are posted once and referred to by index >> >> >> While, in a sense, current uses are much more concerning than future=20 >> uses, with introspection opcodes, it might create substantive additional= =20 >> complexity to ensure that there is always a valid way to add a padding b= yte=20 >> without upsetting a state machine. >> >> As there are now documented use cases for 64-byte transactions that this= =20 >> proposal makes more difficult to do, I recommend replacing the text in t= he=20 >> BIP that says >> >> >> *> 64-byte transactions can only contain a scriptPubKey that lets anyone= =20 >> spend the funds, or one that burns them. * >> With something like: >> >> *> There are documented use cases for 64-byte transactions that this=20 >> proposal makes more difficult to cleanly do, but we do not believe these= =20 >> use cases will ever be valuable or worth protecting.* >> >> Or a more accurate reflection of the BIP-0054 authors' opinion. >> >> Jeremy >> >> --=20 >> You received this message because you are subscribed to the Google Group= s=20 >> "Bitcoin Development Mailing List" group. >> > To unsubscribe from this group and stop receiving emails from it, send an= =20 >> email to bitcoindev+...@googlegroups.com. >> To view this discussion visit=20 >> https://groups.google.com/d/msgid/bitcoindev/123e5545-2eda-4eca-9532-4f4= cea2b83ecn%40googlegroups.com=20 >> >> . >> > --=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/= 8a82e9d6-b013-4b7f-ba9f-f91f50b1bbe3n%40googlegroups.com. ------=_Part_276571_8528284.1777745352552 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Chris,

These examples should work and = could be adapted to a different funding input (I stubbed out the actual sig= nature with just a preimage reveal for simplicity).

<= div>
funding witnessScript: a820ff76f4f923cd475f27097b38226= 40a9b441894f3d4f742fe70e745e986da388e87
funding scriptPubKey: 002080c153db1ea3461a2b70126f853189fc34d7d= 9926f083dfb2bffae8ae2bb1130
funding txid: 166ef40e58f1a62e01d610023ca7935eef372cf3c= 1239d81430dffbd1fe8fe9e
funding tx hex: 02000000010000000000000000000000000000000= 000000000000000000000000000000000ffffffff020101ffffffff01a08601000000000022= 002080c153db1ea3461a2b70126f853189fc34d7d9926f083dfb2bffae8ae2bb11300000000= 0
182 |
spending output scriptPubKey: 020002b2
spending stripped size: 64
spending full size: 114
spending txid: 44c752f499326a59a78259b455875d2961= 08184b7f25b9a0b41bc018af7aedd8
spending wtxid: 1e6eb4de698f079cbaa0fdf47d7ab5e1bb= 4939fae42652f295dd05d15930074d
spending tx stripped hex: 02000000019efee81fbdff0d43819d23c1= f32c37ef5e93a73c0210d6012ea6f1580ef46e160000000000ffffffff01905f01000000000= 004020002b200000000
spending tx full hex: 020000000001019efee81fbdff0d43819d= 23c1f32c37ef5e93a73c0210d6012ea6f1580ef46e160000000000ffffffff01905f0100000= 0000004020002b2020a62697035342064656d6f23a820ff76f4f923cd475f27097b3822640a= 9b441894f3d4f742fe70e745e986da388e8700000000


$ decodraw= transaction $(cat funding_tx.hex)

{
=C2=A0 "txid": "166ef40e58f1a62e01d610023ca7935eef372cf3c1239d814= 30dffbd1fe8fe9e",
=C2=A0 "hash": "166ef40e58f1a62e01d610023ca7935eef37= 2cf3c1239d81430dffbd1fe8fe9e",
=C2=A0 "version": 2,
=C2=A0 "size"= : 96,
=C2=A0 "vsize": 96,
=C2=A0 "weight": 384,
=C2=A0 "lock= time": 0,
=C2=A0 "vin": [
=C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2= =A0 "coinbase": "0101",
=C2=A0 =C2=A0 =C2=A0 "sequence": 4294967295=C2=A0 =C2=A0 }
=C2=A0 ],
=C2=A0 "vout": [
=C2=A0 =C2=A0 = {
=C2=A0 =C2=A0 =C2=A0 "value": 0.00100000,
=C2=A0 =C2=A0 =C2=A0 = "n": 0,
=C2=A0 =C2=A0 =C2=A0 "scriptPubKey": {
=C2=A0 =C2=A0 =C2= =A0 =C2=A0 "asm": "0 80c153db1ea3461a2b70126f853189fc34d7d9926f083dfb2bffae= 8ae2bb1130",
=C2=A0 =C2=A0 =C2=A0 =C2=A0 "desc": "addr(bcrt1qsrq48kc75= drp52mszfhc2vvfls6d0kvjduyrm7etl7hg4c4mzycqmw604m)#2rrnsnlc",
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 "hex": "002080c153db1ea3461a2b70126f853189fc34d7d9926f= 083dfb2bffae8ae2bb1130",
=C2=A0 =C2=A0 =C2=A0 =C2=A0 "address": "bcrt1= qsrq48kc75drp52mszfhc2vvfls6d0kvjduyrm7etl7hg4c4mzycqmw604m",
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 "type": "witness_v0_scripthash"
=C2=A0 =C2=A0 =C2= =A0 }
=C2=A0 =C2=A0 }
=C2=A0 ]
}


$ decodrawtransaction $(cat spending_tx_stripped.hex)


{
=C2=A0 "txid": "44c752f499326a59a78259b455875d296108184b7f25b9= a0b41bc018af7aedd8",
=C2=A0 "hash": "44c752f499326a59a78259b455875d296= 108184b7f25b9a0b41bc018af7aedd8",
=C2=A0 "version": 2,
=C2=A0 "si= ze": 64,
=C2=A0 "vsize": 64,
=C2=A0 "weight": 256,
=C2=A0 "l= ocktime": 0,
=C2=A0 "vin": [
=C2=A0 =C2=A0 {
=C2=A0 =C2=A0 = =C2=A0 "txid": "166ef40e58f1a62e01d610023ca7935eef372cf3c1239d81430dffbd1fe= 8fe9e",
=C2=A0 =C2=A0 =C2=A0 "vout": 0,
=C2=A0 =C2=A0 =C2=A0 "scr= iptSig": {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 "asm": "",
=C2=A0 =C2=A0 = =C2=A0 =C2=A0 "hex": ""
=C2=A0 =C2=A0 =C2=A0 },
=C2=A0 =C2=A0 =C2= =A0 "sequence": 4294967295
=C2=A0 =C2=A0 }
=C2=A0 ],
=C2=A0 = "vout": [
=C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 "value": 0.0009000= 0,
=C2=A0 =C2=A0 =C2=A0 "n": 0,
=C2=A0 =C2=A0 =C2=A0 "scriptPubKe= y": {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 "asm": "512 OP_CHECKSEQUENCEVERIFY",=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 "desc": "raw(020002b2)#vceh5z0j",
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 "hex": "020002b2",
=C2=A0 =C2=A0 =C2=A0 = =C2=A0 "type": "nonstandard"
=C2=A0 =C2=A0 =C2=A0 }
=C2=A0 =C2=A0= }
=C2=A0 ]
}

$ decodrawtransaction $= (cat spending_tx_full.hex)

{
=C2= =A0 "txid": "44c752f499326a59a78259b455875d296108184b7f25b9a0b41bc018af7aed= d8",
=C2=A0 "hash": "1e6eb4de698f079cbaa0fdf47d7ab5e1bb4939fae42652f29= 5dd05d15930074d",
=C2=A0 "version": 2,
=C2=A0 "size": 114,
= =C2=A0 "vsize": 77,
=C2=A0 "weight": 306,
=C2=A0 "locktime": 0,=C2=A0 "vin": [
=C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 "txid": = "166ef40e58f1a62e01d610023ca7935eef372cf3c1239d81430dffbd1fe8fe9e",
= =C2=A0 =C2=A0 =C2=A0 "vout": 0,
=C2=A0 =C2=A0 =C2=A0 "scriptSig": {=C2=A0 =C2=A0 =C2=A0 =C2=A0 "asm": "",
=C2=A0 =C2=A0 =C2=A0 =C2=A0 = "hex": ""
=C2=A0 =C2=A0 =C2=A0 },
=C2=A0 =C2=A0 =C2=A0 "txinwitne= ss": [
=C2=A0 =C2=A0 =C2=A0 =C2=A0 "62697035342064656d6f",
=C2=A0= =C2=A0 =C2=A0 =C2=A0 "a820ff76f4f923cd475f27097b3822640a9b441894f3d4f742fe= 70e745e986da388e87"
=C2=A0 =C2=A0 =C2=A0 ],
=C2=A0 =C2=A0 =C2=A0 = "sequence": 4294967295
=C2=A0 =C2=A0 }
=C2=A0 ],
=C2=A0 "vou= t": [
=C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 "value": 0.00090000,=C2=A0 =C2=A0 =C2=A0 "n": 0,
=C2=A0 =C2=A0 =C2=A0 "scriptPubKey": = {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 "asm": "512 OP_CHECKSEQUENCEVERIFY",
=C2=A0 =C2=A0 =C2=A0 =C2=A0 "desc": "raw(020002b2)#vceh5z0j",
=C2=A0= =C2=A0 =C2=A0 =C2=A0 "hex": "020002b2",
=C2=A0 =C2=A0 =C2=A0 =C2=A0 "= type": "nonstandard"
=C2=A0 =C2=A0 =C2=A0 }
=C2=A0 =C2=A0 }
= =C2=A0 ]
}


```python3#!/usr/bin/env python3
from __future__ import annotations

= import hashlib
import struct


OP_SHA256 =3D 0xA8
= OP_EQUAL =3D 0x87
OP_CHECKSEQUENCEVERIFY =3D 0xB2


def= sha256(b: bytes) -> bytes:
=C2=A0 =C2=A0 return hashlib.sha256(b).= digest()


def hash256(b: bytes) -> bytes:
=C2=A0 = =C2=A0 return hashlib.sha256(hashlib.sha256(b).digest()).digest()


def hash256_be_hex(b: bytes) -> str:
=C2=A0 =C2=A0 return h= ash256(b)[::-1].hex()


def compact_size(n: int) -> bytes= :
=C2=A0 =C2=A0 if n < 0:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 raise Va= lueError("negative compact size")
=C2=A0 =C2=A0 if n < 253:
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 return bytes([n])
=C2=A0 =C2=A0 if n <= =3D 0xFFFF:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return b"\xfd" + struct.pack("= <H", n)
=C2=A0 =C2=A0 if n <=3D 0xFFFFFFFF:
=C2=A0 =C2=A0 = =C2=A0 =C2=A0 return b"\xfe" + struct.pack("<I", n)
=C2=A0 =C2=A0 r= eturn b"\xff" + struct.pack("<Q", n)


def i32(n: int) -&= gt; bytes:
=C2=A0 =C2=A0 return struct.pack("<i", n)

def u32(n: int) -> bytes:
=C2=A0 =C2=A0 return struct.pack("<= I", n)


def u64(n: int) -> bytes:
=C2=A0 =C2=A0 ret= urn struct.pack("<Q", n)


def ser_output(value_sat: int,= script_pubkey: bytes) -> bytes:
=C2=A0 =C2=A0 return u64(value_sat= ) + compact_size(len(script_pubkey)) + script_pubkey


def s= er_input(prev_txid_be_hex: str, vout: int, script_sig: bytes =3D b"", seque= nce: int =3D 0xFFFFFFFF) -> bytes:
=C2=A0 =C2=A0 # Transaction outp= oints serialize txids little-endian.
=C2=A0 =C2=A0 prev_txid_le =3D by= tes.fromhex(prev_txid_be_hex)[::-1]
=C2=A0 =C2=A0 return (
=C2=A0= =C2=A0 =C2=A0 =C2=A0 prev_txid_le
=C2=A0 =C2=A0 =C2=A0 =C2=A0 + u32(v= out)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 + compact_size(len(script_sig))
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 + script_sig
=C2=A0 =C2=A0 =C2=A0 =C2=A0 += u32(sequence)
=C2=A0 =C2=A0 )


# --------------------= ------------------------------------------------
# Funding transaction=
# -------------------------------------------------------------------= -
#
# This is a coinbase-like funding transaction for a decode/te= st vector.
# It pays 100_000 sats to a native P2WSH output.
#
# witnessScript:
#
# =C2=A0 OP_SHA256 <sha256("bip54 demo")&= gt; OP_EQUAL
#
# The spending transaction must reveal the preimag= e "bip54 demo" in witness.

secret =3D b"bip54 demo"
secret_= hash =3D sha256(secret)

witness_script =3D (
=C2=A0 =C2=A0 = bytes([OP_SHA256])
=C2=A0 =C2=A0 + bytes([0x20]) =C2=A0 =C2=A0 =C2=A0 = # push 32 bytes
=C2=A0 =C2=A0 + secret_hash
=C2=A0 =C2=A0 + bytes= ([OP_EQUAL])
)

# Native v0 P2WSH scriptPubKey:
#
= # =C2=A0 OP_0 <sha256(witness_script)>
#
funding_script_pub= key =3D b"\x00\x20" + sha256(witness_script)

coinbase_script_sig= =3D b"\x01\x01" =C2=A0# BIP34-style height=3D1 push; enough for a decode v= ector.

funding_tx =3D (
=C2=A0 =C2=A0 i32(2)
=C2=A0 = =C2=A0 + compact_size(1)
=C2=A0 =C2=A0 + bytes(32) =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# coinbase prevout txid =3D 0x= 00..00
=C2=A0 =C2=A0 + u32(0xFFFFFFFF) =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0# coinbase prevout index
=C2=A0 =C2=A0 + compact_size(len(co= inbase_script_sig))
=C2=A0 =C2=A0 + coinbase_script_sig
=C2=A0 = =C2=A0 + u32(0xFFFFFFFF)
=C2=A0 =C2=A0 + compact_size(1)
=C2=A0 = =C2=A0 + ser_output(100_000, funding_script_pubkey)
=C2=A0 =C2=A0 + u3= 2(0)
)

funding_txid =3D hash256_be_hex(funding_tx)

# ----------------------------------------------------------------= ----
# Spending transaction
# -----------------------------------= ---------------------------------
#
# This spends funding_tx outp= ut 0.
#
# The sole output scriptPubKey is:
#
# =C2=A0 &= lt;512> OP_CHECKSEQUENCEVERIFY
#
# Minimal ScriptNum encoding = for decimal 512 is little-endian 00 02,
# so the full script is:
= #
# =C2=A0 02 00 02 b2
#
# This spending transaction has:#
# =C2=A0 witness-stripped size =3D exactly 64 bytes
# =C2=A0= full witness serialization =3D larger than 64 bytes

csv512_scri= pt_pubkey =3D bytes([0x02, 0x00, 0x02, OP_CHECKSEQUENCEVERIFY])

= spending_input =3D ser_input(
=C2=A0 =C2=A0 prev_txid_be_hex=3Dfunding= _txid,
=C2=A0 =C2=A0 vout=3D0,
=C2=A0 =C2=A0 script_sig=3Db"",=C2=A0 =C2=A0 sequence=3D0xFFFFFFFF,
)

spending_output = =3D ser_output(90_000, csv512_script_pubkey)

spending_tx_strippe= d =3D (
=C2=A0 =C2=A0 i32(2)
=C2=A0 =C2=A0 + compact_size(1)
=C2=A0 =C2=A0 + spending_input
=C2=A0 =C2=A0 + compact_size(1)
= =C2=A0 =C2=A0 + spending_output
=C2=A0 =C2=A0 + u32(0)
)
# P2WSH witness stack:
#
# =C2=A0 <secret> <witness_s= cript>
#
spending_witness =3D (
=C2=A0 =C2=A0 compact_siz= e(2)
=C2=A0 =C2=A0 + compact_size(len(secret))
=C2=A0 =C2=A0 + se= cret
=C2=A0 =C2=A0 + compact_size(len(witness_script))
=C2=A0 =C2= =A0 + witness_script
)

spending_tx_full =3D (
=C2=A0 = =C2=A0 i32(2)
=C2=A0 =C2=A0 + b"\x00\x01" =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 # SegWit marker + flag
=C2=A0 =C2=A0 + compact_si= ze(1)
=C2=A0 =C2=A0 + spending_input
=C2=A0 =C2=A0 + compact_size= (1)
=C2=A0 =C2=A0 + spending_output
=C2=A0 =C2=A0 + spending_witn= ess
=C2=A0 =C2=A0 + u32(0)
)

assert len(spending_tx_st= ripped) =3D=3D 64
assert csv512_script_pubkey.hex() =3D=3D "020002b2"<= br />
print("funding witnessScript:", witness_script.hex())
print= ("funding scriptPubKey: ", funding_script_pubkey.hex())
print("funding= txid: =C2=A0 =C2=A0 =C2=A0 =C2=A0 ", funding_txid)
print("funding tx = hex: =C2=A0 =C2=A0 =C2=A0 ", funding_tx.hex())
print()
print("spe= nding output scriptPubKey:", csv512_script_pubkey.hex())
print("spendi= ng stripped size: =C2=A0 =C2=A0 =C2=A0", len(spending_tx_stripped))
pr= int("spending full size: =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0", len(spending_= tx_full))
print("spending txid: =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 ", hash256_be_hex(spending_tx_stripped))
print("spending wt= xid: =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0", hash256_be_hex(spen= ding_tx_full))
print("spending tx stripped hex: =C2=A0 =C2=A0", spendi= ng_tx_stripped.hex())
print("spending tx full hex: =C2=A0 =C2=A0 =C2= =A0 =C2=A0", spending_tx_full.hex())
```

On Saturday, May= 2, 2026 at 8:56:25=E2=80=AFAM UTC-7 Chris Stewart wrote:
I do con= cede your point that witness stripping isn't well understood by the gen= eral community. Here is a writeup I did for readers of the mailing list tha= t may not understand what Jeremy is talking about the characteristics of a = 64 byte transaction[0]. There is a big distinction between pre-segwit 64 by= te transactions and segwit 64 byte transactions.


> A transaction that donates to a f= uture miner from a segwit (any=20 version) output via a spend to something like <512> OP_CSV (->=20 push2 bytes 512 csv -> 0x02 0x00 0x02 0xb2)

I find=20 this confusing. Can you give 2 hex encoded transactions (funding=20 transaction, spending transaction) that do this? regtest is fine, i can=20 just decode locally.

Splitting hairs=20 semantically if understand the transactions you are proposing above,=20 "donating" to a "future miner" i.e. sending money to anyone (not a specific someone) in the future that can mine a block - doesn't seem much different to m= e than "anyone can spend the funds". I'll await your transacti= ons though=20 in the case that I am missing something.


On Fri, May 1, 2026 = at 4:15=E2=80=AFPM jeremy <je= remy....@gmail.com> wrote:
For fun, let's = start with a pop-quiz:

Select all that apply: Ther= e can exist a transaction of ___ bytes serialized size that BIP-0054's = 64-byte restriction invalidates:

A) 64 Bytes
B) 0 Bytes
C) 1= .5MB
D) 32 Bytes
E) 5MB


The answer is A, 64 Bytes, and --= perhaps surprisingly -- C, 1.5MB.=C2=A0

Why is this the case?
BIP-0054 uses the term 64-byte transaction, but defines it as follows:
> Transactions whose witness-stripped serialized siz= e is exactly 64 bytes are invalid.

In a [perso= nally run] straw-poll of devs at a recent conference, no-one knew this prec= ise edge condition or that the transactions could have a meaningful witness= . For clarity, the restriction on bytes is on INVALID_TX_NONWITNESS_SIZE, n= ot on the size with Witness.

Therefore, it is more accur= ate to refer to this in all sentences throughout the BIP as:
<= br>
> transactions with exactly 64 bytes of non-witness= data,

due to the propensity for confusion.

BIP-0054 also makes a comment that the transactions = it invalidates are essentially useless:

> 64= -byte transactions can only contain a scriptPubKey that lets anyone spend t= he funds, or one that burns them.

This is = not strictly correct. Here are a few examples of current and future uses fo= r 64-byte transactions:

Current Uses:<= /div>
- A transaction that donates to a future miner from a segwit= (any version) output via a spend to something like <512> OP_CSV (-&g= t; push2 bytes 512 csv -> 0x02 0x00 0x02 0xb2)
- That same out= put which is used as a connector output for things that should be claimed b= y a miner at a future time
- Pay-to-Anchor / ephemeral anchor ou= tputs -- while typically p2a is for txns you want to add a subsidy ability,= a 64-byte txn could be used to shim a keyed anchor to a p2a output after a= certain delay.

Future Uses:
= - Future work which might use output scripts for e.g. Transaction Sponsor e= ncodings
- Future covenants work which encodes time-of-creat= ion run scripts that e.g. quine an input; possibly in conjunction with spon= sors
- Future where we have expensive reusable PQ or Contra= ct public keys that are posted once and referred to by index

=

While, in a sense, current uses are much more con= cerning than future uses, with introspection opcodes, it might create subst= antive additional complexity to ensure that there is always a valid way to = add a padding byte without upsetting a state machine.

As there are= now documented use cases for 64-byte transactions that this proposal makes= more difficult to do, I recommend replacing the text in the BIP that says<= br>
> 64-byte transactions can only contain a scriptPubKey that le= ts anyone spend the funds, or one that burns them.

With somethi= ng like:

> There are documented use cases for 64-b= yte transactions that this proposal makes more difficult to cleanly do, but= we do not believe these use cases will ever be valuable or worth protectin= g.

Or a more accurate reflection of the= BIP-0054 authors' opinion.

Jeremy
<= div>

--
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 bitcoindev+...@googlegro= ups.com.
To view this discussion visit https= ://groups.google.com/d/msgid/bitcoindev/123e5545-2eda-4eca-9532-4f4cea2b83e= cn%40googlegroups.com.

--
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/msgid/bitcoind= ev/8a82e9d6-b013-4b7f-ba9f-f91f50b1bbe3n%40googlegroups.com.
------=_Part_276571_8528284.1777745352552-- ------=_Part_276570_1438884530.1777745352552--