From mboxrd@z Thu Jan 1 00:00:00 1970 Delivery-date: Tue, 16 Jun 2026 13:48:32 -0700 Received: from mail-oa1-f62.google.com ([209.85.160.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 1wZahx-0002M3-CZ for bitcoindev@gnusha.org; Tue, 16 Jun 2026 13:48:32 -0700 Received: by mail-oa1-f62.google.com with SMTP id 586e51a60fabf-43d33c10c62sf4498946fac.2 for ; Tue, 16 Jun 2026 13:48:28 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1781642903; cv=pass; d=google.com; s=arc-20240605; b=AmlRHlWXVSyPYesVHDPkIpa/BN7gqGW6eQhMZrts+q4s7H6mIb0V0JhdFifnXwi7Fp Qoe3R/TZhg5+IO5/GO3akQ+GDExe3z0x5xNogyna1h9mtaFZIWNZE4GVr4Rr+xZ2GKs7 v0DzlMqiWWLgpldFId9aczp92HOdairQ4ERcYUL8vc6VAFFc3+GNTeX19u1DdyZm8vej jK6gPn/6vVJW7N0gzjRjcD8s1ToYstxBGDQ9ljPn0rk2LKiKD4YAFzpbT/jOLnPZ+801 aFlwdzr18q3+sB2Tt8Xg13li1xzcMGNsMUnfXs5acrXBQuZVE2o/HN7l+yUkxoqKbflQ TFjg== ARC-Message-Signature: i=2; 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:reply-to:mime-version:feedback-id :references:in-reply-to:message-id:subject:cc:from:to:date :dkim-signature; bh=fzbLfRKzI5TwSOJ6/A3gfhItL08Va9YwXg4O1Zf+9OA=; fh=2nZBeoXI3s0lOsnVfq7KA9vEnPnL/xkXO4KWzHiPGiI=; b=dHjnI8kFkHTly4KNIpaxbeLy2zGn7l+Q8I2yM35ZZaJEdUDappGC8zwseJmO7F8SnZ tn1Zb8BHQikA7Aiw5NUMj6zYRy4XvtGt6NbjyCJQe3CbJ6GcogwWlIcCwcqgWyKIFAm5 bDaaDsIgABFz81uVaWXI6UyV1BXhm8lBicBHJPuzXM9AeqK8dgr1WKSBhSYtHxn2XeNm h5yS3OXEuuj9pozR8ZZVfcf7fBkUMuuq/ma7jNisd0srHomFIPBzEcdTa22c+YbISmCO GE5RlCFWT5cjd/3XA4JGrkyPA01FUwdlKBPrwc8o+YGmRkY+R4cxAtM5jLCTiGQR4VrD ghXg==; darn=gnusha.org ARC-Authentication-Results: i=2; gmr-mx.google.com; dkim=pass header.i=@protonmail.com header.s=protonmail3 header.b=MZYn70O8; spf=pass (google.com: domain of darosior@protonmail.com designates 79.135.106.119 as permitted sender) smtp.mailfrom=darosior@protonmail.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=protonmail.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20251104; t=1781642903; x=1782247703; darn=gnusha.org; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:reply-to :x-original-authentication-results:x-original-sender:mime-version :feedback-id:references:in-reply-to:message-id:subject:cc:from:to :date:from:to:cc:subject:date:message-id:reply-to; bh=fzbLfRKzI5TwSOJ6/A3gfhItL08Va9YwXg4O1Zf+9OA=; b=WVPRJYKcORL7AaZG6i/BAXXW1RVS3HgE4kOOSLCdXKkHtiCvOVAYKb2l/8Xvgpxa7i gO88oEKfAFSDFnVW3LupiuhBQMoyViQtziIqHeiVzbgOK6Vr6iCgb6SNkgDqIbGLwGMH v/EQFH5J50p9Nkgj4PdLCns+hhqF6uMMVPmgtH4anhz2WV0gBLp9qnPAr+ZPK8cFq+vf JoH5yfYNjeJTr190yeMKAg4oXeME4LA7JDi9JnVxWeGCNZvVwXAuSa8wLRc18zddRcjK XWIDd3k80kNiBJfVE8dBK9uJ/RC9VUUpaPQUrftLi9vyiLBL68/KF0ffdCbqlLFUwOR+ i0CA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781642903; x=1782247703; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:reply-to :x-original-authentication-results:x-original-sender:mime-version :feedback-id:references:in-reply-to:message-id:subject:cc:from:to :date:x-beenthere:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=fzbLfRKzI5TwSOJ6/A3gfhItL08Va9YwXg4O1Zf+9OA=; b=a5w8UsfZ7TSMNpDqoEyJUP69Cf+xXgsRWbeQJfrr/yaCbNmtRpO9DLuVmf+M8ToJR4 le3WG+Z8fE6Mq7tmzgC+C/iGfqtH1ohJgNRiDNLTly/HCIeAPiMms+hRIy1JlyF8TWVO KyCuOayTRdBAIfSdCDpqbyfbF7mBBp3GM5ZBCmPnXNh+z8ERIjfzx3W5H33Wy2TMEvAz tm5B/YKS8ZqpQmmg8zL5oo/kUpR7Ljey4uY/Ks11G1Agk/hhGYEnghdWnvE/WJPpPnJP G5gDCVZRQU59QVVpFWKaQjBEIlNctQ0BH2z4KjYQc0QzyZefhf2HNt+VuUDv8ch+bV8u HbDw== X-Forwarded-Encrypted: i=2; AFNElJ+YQkiOGnfFs2rKLVpihAn3nWWLzVFB5VEDyu8/ILoTvwm+XM9VUo/VO6+uPI4njHKTUWeHqJgc+QYR@gnusha.org X-Gm-Message-State: AOJu0YwKCkB0RCBZFXe+Vi6QxxgkO5bg24lg2kjJXYR1Onw5BDGs4ODi mDFs4ryiL0WUOLHXZhKTtyz6wjgMroIVPMtFxQc/hd5zFXqEecBreD0p X-Received: by 2002:a05:6871:3390:b0:409:77a9:f951 with SMTP id 586e51a60fabf-446901f7cd0mr570459fac.11.1781642902668; Tue, 16 Jun 2026 13:48:22 -0700 (PDT) X-BeenThere: bitcoindev@googlegroups.com; h="AX0PUUdzFl7hvC2/1iZEXVa8l2xQk27FcbZXoKQVNo9S8CiUNA==" Received: by 2002:a05:6870:3276:b0:42f:eb75:2e78 with SMTP id 586e51a60fabf-44262f12572ls2493775fac.2.-pod-prod-06-us; Tue, 16 Jun 2026 13:48:18 -0700 (PDT) X-Received: by 2002:a05:6808:190d:b0:467:2a6e:adb6 with SMTP id 5614622812f47-48942861330mr1095691b6e.8.1781642898257; Tue, 16 Jun 2026 13:48:18 -0700 (PDT) Received: by 2002:a05:6402:a504:20b0:670:416a:5ab4 with SMTP id 4fb4d7f45d1cf-69546b893f6msa12; Tue, 16 Jun 2026 13:43:04 -0700 (PDT) X-Received: by 2002:a17:907:720e:b0:c03:c9a8:42f4 with SMTP id a640c23a62f3a-c05a2749098mr73735366b.16.1781642583067; Tue, 16 Jun 2026 13:43:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1781642583; cv=none; d=google.com; s=arc-20240605; b=DF8YshQKCsupUOODAIP+KOwvfPXn+cAOkh2VJNKfJwuc7n7h+DHNb2yAuVCVF0ICK/ lw29iuaQc4f3gq0MTSQ9Ig38CDlYw0Ubai0fRjrtYZ/Lxd3khXQQYKrUsUajTuAp+Yfl rJOJELFfrVeRr4KPi6jaapQ1fs+HGBHBSRU55y7SFpoS2RU8tSIUMdpfqFmzBkRMb9wP G+WuDD04N73lIOY177ni6Tu7GvtwWTYqc3K9M7R1gF4IKtzW5tKFkVdSUhTKqvzoLMUf lnz3zgMwyEXhiA0LyytxjMbF8CaKyHfo7vr1eDLqyxCcnr9UGpFz0vj9hmu5M06HwYoR tjzg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=mime-version:feedback-id:references:in-reply-to:message-id:subject :cc:from:to:date:dkim-signature; bh=8pFxGBI5l8eq9+4DmB0Mmj1L/Fp+aRY4ph062tLhPhE=; fh=+Duu3Cp77aXfHDD1ma61XeBuViahPkcQ600hmLognUE=; b=iB3XdlaE8lRIGdSLWYPmqrtdLkQIJBWZv4mIbSuXMmUWfbx2OYeeN+csACityKQSck EfOSYlRyBpY2dG6nFHSB4ssp5TQhmu8Sqa/w9OJH/MYbb8F2WMpgaQktgi9U8oVmTKhS MwAjPjAEtDWjCruUoAulSYk/7gcmhLJVqzVQuJnQREGoM2sYKDK/obbJ3Wfucpx3PiC3 SYDioIvxh5Byd6xFjztDsuT7Nk5UkajI9a2SWaVEOtMoAzlWVyVA9EyqrXFgvPg+NMXr o+q4fyuF8TeZGBZlI4SkalV44BSHB/dsaGWNAn5SMgbK38TCln5jiKBknIn3VeJNFS33 qnOQ==; dara=google.com ARC-Authentication-Results: i=1; gmr-mx.google.com; dkim=pass header.i=@protonmail.com header.s=protonmail3 header.b=MZYn70O8; spf=pass (google.com: domain of darosior@protonmail.com designates 79.135.106.119 as permitted sender) smtp.mailfrom=darosior@protonmail.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=protonmail.com Received: from mail-106119.protonmail.ch (mail-106119.protonmail.ch. [79.135.106.119]) by gmr-mx.google.com with ESMTPS id 4fb4d7f45d1cf-693791e2335si369050a12.2.2026.06.16.13.43.02 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 16 Jun 2026 13:43:03 -0700 (PDT) Received-SPF: pass (google.com: domain of darosior@protonmail.com designates 79.135.106.119 as permitted sender) client-ip=79.135.106.119; Date: Tue, 16 Jun 2026 20:42:56 +0000 To: jeremy From: "'Antoine Poinsot' via Bitcoin Development Mailing List" Cc: Bitcoin Development Mailing List Subject: Re: [bitcoindev] Re: Prohibit Merkle Internal Node Preimages That Encode Minimal 64-Byte Transactions Message-ID: In-Reply-To: <2cae3f35-2058-4e41-8fe9-d2ef06259e0dn@googlegroups.com> References: <2cae3f35-2058-4e41-8fe9-d2ef06259e0dn@googlegroups.com> Feedback-ID: 7060259:user:proton X-Pm-Message-ID: d9e57819bdcaf32ca27d021d3eee66fb7c94a466 MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="b1=_ITTgH2aq8BD1AKW8OUVL89oor6hNAUKsfP52PvAXTs" X-Original-Sender: darosior@protonmail.com X-Original-Authentication-Results: gmr-mx.google.com; dkim=pass header.i=@protonmail.com header.s=protonmail3 header.b=MZYn70O8; spf=pass (google.com: domain of darosior@protonmail.com designates 79.135.106.119 as permitted sender) smtp.mailfrom=darosior@protonmail.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=protonmail.com X-Original-From: Antoine Poinsot Reply-To: Antoine Poinsot 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: -1.0 (-) --b1=_ITTgH2aq8BD1AKW8OUVL89oor6hNAUKsfP52PvAXTs Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable It would align with a deployed system. Other deployed systems use different= workarounds. For instance BitVM uses the alternative mitigation also proposed by Sergio.= BitVM's implementation: https://github.com/BitVM/BitVM/pull/295. Sergio's = description of the idea: https://bitslog.com/2018/08/21/simple-change-to-th= e-bitcoin-merkleblock-command-to-protect-from-leaf-node-weakness-in-transac= tion-merkle-tree/. This post notably opens with: > While this solves the problem, it is by no means a =E2=80=9Cclean=E2=80= =9D solution: it creates false-negative cases (with very low probability) a= nd it reduces verification efficiency. Other bridge applications check the depth of the proof vs a proof for the c= oinbase transaction: https://github.com/threshold-network/tbtc-v2/blob/cf4d= 12f71b08511bc2185802be88e302b7bef656/solidity/contracts/bridge/BitcoinTx.so= l#L194-L197. More importantly, this is not a good standard by which to judge mitigations= . The goal of a consensus-enforced mitigation is to make SPV verifiers secu= re without requiring them to implement one of the workarounds. Your proposa= l, besides the substantial costs it would impose on full nodes, does not ac= hieve this goal. Simply invalidating 64-byte transactions does (for all kno= wn and non-esoteric imaginable ones). On Tuesday, June 16th, 2026 at 4:22 PM, jeremy w= rote: > Adding a note & reference that Rootstock uses a similar mitigation for it= 's SPV proofs: > > See the below code: > https://github.com/rsksmart/bitcoinj-thin/blob/f89816871d644436e34cd8d0a7= 0c3c8ef41b0836/src/main/java/co/rsk/bitcoinj/core/PartialMerkleTree.java#L1= 87 > > And SDL's blog post on the topic: https://bitslog.com/2018/06/09/leaf-nod= e-weakness-in-bitcoin-merkle-tree-design > > So enforcing this rule would align with existing deployed systems. > On Monday, June 1, 2026 at 2:02:51=E2=80=AFPM UTC-4 jeremy wrote: > >> Esteemed Colleagues, >> >> As a result of some of my research on 64-byte transactions, I'd like to = discuss an alternative soft fork proposal that preserves the ability to enc= ode 64-byte transactions while offering protection to SPV users (who must m= ake a small patch to validate the path property). >> >> The rule, stated simply, is: >> >> A block is invalid if any Merkle Tree 64-byte preimage has the exact byt= e structure of a minimal one-input, one-output, witness stripped transactio= n. >> >> [With the miracle of GPT,] I've drafted a relatively complete BIP for di= scussion. >> >> Happy International Children's Day, >> >> Jeremy >> >> p.s. I will later propose potentially a couple other mitigations separat= ely, for discussion as well. >> >> --------------------------------------------------------------- >> >> BIP: TBD >> Layer: Consensus (soft fork) >> Title: Prohibit Merkle Internal Node Preimages That Encode Minimal 64-By= te Transactions >> Author: TBD >> Status: Draft >> Type: Standards Track >> Created: 2026-06-01 >> License: BSD-2-Clause >> >> Abstract >> >> This document specifies a consensus rule that invalidates a block if any= transaction Merkle tree internal node preimage encodes a minimal 64-byte t= ransaction. >> >> For each internal Merkle node, Bitcoin computes: >> >> parent =3D SHA256d(left || right) >> >> where left and right are 32-byte hashes. The 64-byte string left || righ= t is the internal node preimage. >> >> After activation, a block is invalid if any such 64-byte preimage has th= e exact byte structure of a minimal one-input, one-output, non-witness tran= saction. >> >> This prevents a 64-byte transaction serialization from being malleated i= nto an internal Merkle node preimage in SPV transaction inclusion proofs. I= t does not make 64-byte transactions invalid in general. >> >> Motivation >> >> Bitcoin transaction identifiers and transaction Merkle internal nodes ar= e both computed with double SHA256: >> >> txid =3D SHA256d(serialized_transaction) >> >> parent =3D SHA256d(left_child_hash || right_child_hash) >> >> If a valid transaction serialization is exactly 64 bytes, the same byte = string can also be interpreted as the concatenation of two 32-byte Merkle c= hild hashes: >> >> serialized_transaction =3D left_child_hash || right_child_hash >> >> This creates an ambiguity between a transaction leaf preimage and an int= ernal node preimage. >> >> An SPV verifier that accepts a Merkle proof without authenticating the f= ull tree shape can be made to accept a proof terminating at an internal nod= e rather than at an actual transaction leaf. >> >> This proposal removes that ambiguity by forbidding Merkle internal node = preimages that have the only practical 64-byte transaction encoding shape. >> >> SegWit and transaction identifiers >> >> Since SegWit activation, Bitcoin transactions have two related identifie= rs: >> >> txid =3D SHA256d(legacy serialization) >> >> wtxid =3D SHA256d(witness serialization) >> >> The distinction is important for understanding this proposal. >> >> A SegWit transaction is serialized on the wire as: >> >> nVersion >> >> marker >> >> flag >> >> vin >> >> vout >> >> witness >> >> nLockTime >> >> where: >> >> marker =3D 0x00 >> >> flag =3D 0x01 >> >> The marker and flag bytes indicate that witness data is present. >> >> However, the transaction identifier (txid) is not computed from this wit= ness serialization. Instead, the txid is computed from the legacy serializa= tion: >> >> nVersion >> >> vin >> >> vout >> >> nLockTime >> >> with the marker, flag, and witness fields omitted. >> >> Therefore: >> >> txid =3D SHA256d(non-witness serialization) >> >> while: >> >> wtxid =3D SHA256d(full witness serialization) >> >> The transaction Merkle root committed in the block header is built from = transaction identifiers (txids), not witness transaction identifiers (wtxid= s). >> >> Consequently: >> >> Merkle root =3D Merkle(txid_0, txid_1, ..., txid_n) >> >> and not: >> >> Merkle(wtxid_0, wtxid_1, ..., wtxid_n) >> >> This means that the marker byte (0x00), flag byte (0x01), and witness da= ta never appear in the transaction Merkle tree committed by the block heade= r. >> >> SegWit does define a separate witness Merkle tree whose root is committe= d through the coinbase witness commitment, but that witness Merkle tree is = distinct from the transaction Merkle tree discussed in this proposal. >> >> As a result, the ambiguity addressed by this proposal concerns only tran= saction identifiers (txids) and the transaction Merkle root. The SegWit mar= ker and flag bytes are irrelevant to the transaction Merkle root because th= ey are excluded from txid serialization. >> >> Minimal 64-byte transaction shape >> >> This proposal is concerned with the serialization used to compute a tran= saction's txid. >> >> For legacy transactions, and for SegWit transactions when computing the = txid, the serialization format is: >> >> 4 bytes nVersion >> >> 1 byte vin count =3D 0x01 >> >> 36 bytes prevout >> >> 1 byte scriptSig length =3D x >> >> x bytes scriptSig >> >> 4 bytes nSequence >> >> 1 byte vout count =3D 0x01 >> >> 8 bytes nValue >> >> 1 byte scriptPubKey length =3D y >> >> y bytes scriptPubKey >> >> 4 bytes nLockTime >> >> Notably, this serialization does not include: >> >> marker >> >> flag >> >> witness stack >> >> because those fields are excluded from txid computation. >> >> The fixed overhead is: >> >> 4 + 1 + 36 + 1 + 4 + 1 + 8 + 1 + 4 =3D 60 bytes >> >> Therefore, for total serialized size 64: >> >> x + y =3D 4 >> >> There are exactly five possible script-length splits: >> >> scriptSig length scriptPubKey length >> >> 0 4 >> >> 1 3 >> >> 2 2 >> >> 3 1 >> >> 4 0 >> >> This proposal defines a forbidden Merkle internal node preimage as a 64-= byte byte string satisfying one of those five layouts and whose single outp= ut value is in the consensus money range. >> >> Specification >> >> After activation, a block is invalid if any transaction Merkle internal = node preimage encodes a minimal 64-byte transaction. >> >> For every internal Merkle parent computation in the transaction Merkle t= ree: >> >> parent =3D SHA256d(left || right) >> >> where left and right are 32-byte child hashes, define: >> >> P =3D left || right >> >> The block is invalid if P satisfies all of the following: >> >> - >> >> P[4] =3D=3D 0x01. >> >> - >> >> P[41] is one of 0, 1, 2, 3, 4. >> >> - >> >> Let x =3D P[41]. >> >> - >> >> Let sequence_pos =3D 42 + x. >> >> - >> >> Let vout_count_pos =3D sequence_pos + 4. >> >> - >> >> Let value_pos =3D vout_count_pos + 1. >> >> - >> >> Let scriptpubkey_len_pos =3D value_pos + 8. >> >> - >> >> P[vout_count_pos] =3D=3D 0x01. >> >> - >> >> P[scriptpubkey_len_pos] =3D=3D 4 - x. >> >> - >> >> Let locktime_pos =3D scriptpubkey_len_pos + 1 + (4 - x). >> >> - >> >> locktime_pos + 4 =3D=3D 64. >> >> - >> >> The 8-byte little-endian integer at P[value_pos..value_pos+7] is in Mone= yRange. >> >> Equivalently, the forbidden preimage is a 64-byte serialization of a one= -input, one-output, non-witness transaction with single-byte CompactSize co= unts and script lengths, where the two script lengths sum to 4 and the outp= ut value is in range. >> >> For clarity, "non-witness transaction" here refers to the serialization = used for txid computation. Even for SegWit transactions, the transaction Me= rkle tree uses txids, so the marker byte, flag byte, and witness data are e= xcluded. >> >> This rule applies to every transaction Merkle internal node used to comp= ute the block header's transaction Merkle root. >> >> Odd-entry duplication >> >> If a Merkle level has an odd number of entries, Bitcoin duplicates the f= inal hash: >> >> parent =3D SHA256d(last || last) >> >> The preimage: >> >> last || last >> >> MUST be checked by the same rule. >> >> SPV verification rule >> >> An SPV verifier relying on this soft fork MUST reject a Merkle proof if = any branch preimage in the proof encodes a minimal 64-byte transaction unde= r the predicate above. >> >> For each branch step, the verifier knows: >> >> - >> >> The current hash. >> >> - >> >> The sibling hash. >> >> - >> >> The branch direction. >> >> It reconstructs: >> >> P =3D left_child_hash || right_child_hash >> >> The verifier MUST check: >> >> IsForbiddenMerkleInternalNodePreimage(P) =3D=3D false >> >> for every branch preimage in the proof. >> >> If any branch preimage passes the forbidden-preimage predicate, the proo= f MUST be rejected. >> >> The verifier still performs the ordinary Merkle path computation and blo= ck header proof-of-work validation. >> >> Rationale >> >> The known 64-byte transaction SPV malleability issue requires a byte str= ing that is both: >> >> a valid 64-byte transaction serialization >> >> and: >> >> a transaction Merkle internal node preimage >> >> This proposal forbids that overlap at the Merkle internal node boundary. >> >> The rule is narrower than invalidating all 64-byte transactions. A 64-by= te transaction remains valid unless its exact serialization appears as a tr= ansaction Merkle internal node preimage in the same block's transaction Mer= kle tree. >> >> The rule also avoids adding a general transaction validity rule that exi= sts only to protect Merkle proof semantics. >> >> Why SegWit does not eliminate the ambiguity >> >> It is sometimes assumed that SegWit automatically removes this ambiguity= because SegWit transactions contain the marker and flag bytes: >> >> 00 01 >> >> However, the ambiguity exists at the txid layer, not at the witness-seri= alization layer. >> >> The transaction Merkle root in the block header is computed from txids, = and txids are computed from the serialization that excludes: >> >> marker >> >> flag >> >> witness >> >> Therefore the relevant byte string remains: >> >> nVersion >> >> vin >> >> vout >> >> nLockTime >> >> exactly as before SegWit. >> >> The witness serialization affects the wtxid, but the block header's tran= saction Merkle root does not commit to wtxids. >> >> As a result, the existence of the SegWit marker and flag bytes does not = prevent a txid preimage from having the same byte structure as a Merkle int= ernal node preimage. >> >> The ambiguity addressed by this proposal therefore remains relevant in t= he SegWit era. >> >> Contrast with a 64-byte transaction invalidity rule >> >> A direct alternative is: >> >> A transaction is invalid if its serialized size is exactly 64 bytes. >> >> That rule has several advantages: >> >> - >> >> It is simple to specify. >> >> - >> >> It is simple for SPV verifiers to implement. >> >> - >> >> It removes the original ambiguity by eliminating all valid 64-byte trans= action leaves. >> >> However, it is not correct to describe that rule as automatically fixing= all light clients. >> >> A 64-byte transaction invalidity rule protects an SPV verifier only if t= he verifier enforces the new rule when interpreting the claimed transaction= . Existing or application-specific SPV verifiers that merely receive a byte= string and a Merkle branch may remain vulnerable if they do not parse the = claimed transaction and reject exactly-64-byte transaction serializations. >> >> More generally, a consensus rule invalidating 64-byte transactions does = not prevent arbitrary internal node preimages from existing. It only preven= ts those preimages from being valid Bitcoin transactions under upgraded con= sensus rules. A bridge, wallet, or deposit system that accepts SPV-style pr= oofs but performs incomplete transaction parsing may still be induced to tr= eat an internal node preimage as an application-level event. >> >> For example, suppose an application-level SPV verifier treats a proved b= yte string as a "deposit" if some field inside the alleged transaction matc= hes a registered deposit address, deposit script, or deposit commitment, bu= t does not fully enforce the upgraded transaction-validity rule. An attacke= r may be able to grind child hashes so that: >> >> left_child_hash || right_child_hash >> >> has bytes that the application interprets as a deposit transaction or de= posit commitment. In some systems, the attacker may also be able to choose = or register deposit data that matches bytes already present in the left-han= d side of an internal node preimage. >> >> This is not a failure of upgraded full-node consensus. It is a failure o= f the assumption that changing full-node transaction validity automatically= upgrades every SPV verifier and every bridge, wallet, or application that = consumes SPV-style proofs. >> >> Therefore, both approaches require light-client changes: >> >> 64-byte transaction invalidity: >> >> Light clients must reject claimed 64-byte transaction serializations. >> >> Merkle-internal-node preimage invalidity: >> >> Light clients must reject proofs containing forbidden internal branch pr= eimages. >> >> The 64-byte transaction invalidity rule is simpler for light clients tha= t correctly implement it, but it is broader at the transaction layer. This = proposal places the rule at the Merkle ambiguity boundary and preserves 64-= byte transactions generally. >> >> In summary: >> >> 64-byte transaction invalidity: >> >> - Simpler SPV rule when implemented correctly. >> >> - Broader transaction validity change. >> >> - Invalidates all 64-byte transactions. >> >> - Does not automatically fix SPV applications that fail to enforce the n= ew rule. >> >> Merkle-internal-node preimage invalidity: >> >> - Preserves 64-byte transactions generally. >> >> - Places the rule at the Merkle ambiguity boundary. >> >> - Requires SPV verifiers to parse all branch preimages. >> >> - Directly forbids the ambiguous internal-node preimage condition. >> >> Minimal C++ implementation sketch >> >> This implementation checks only the minimal forbidden 64-byte shape. It = does not invoke the full transaction deserializer. >> >> The function returns true if the 64-byte preimage is forbidden. >> >> static constexpr int64_t COIN =3D 100000000; >> >> static constexpr int64_t MAX_MONEY =3D 21000000 * COIN; >> >> static inline bool MoneyRange(int64_t nValue) >> >> { >> >> return nValue >=3D 0 && nValue <=3D MAX_MONEY; >> >> } >> >> static inline uint64_t ReadLE64(const unsigned char* p) >> >> { >> >> return uint64_t{p[0]} >> >> | (uint64_t{p[1]} << 8) >> >> | (uint64_t{p[2]} << 16) >> >> | (uint64_t{p[3]} << 24) >> >> | (uint64_t{p[4]} << 32) >> >> | (uint64_t{p[5]} << 40) >> >> | (uint64_t{p[6]} << 48) >> >> | (uint64_t{p[7]} << 56); >> >> } >> >> static bool IsForbiddenMerkleInternalNodePreimage64(const unsigned char = p[64]) >> >> { >> >> // Minimal 64-byte legacy transaction shape: >> >> // >> >> // 4 bytes nVersion >> >> // 1 byte vin count =3D 0x01 >> >> // 36 bytes prevout >> >> // 1 byte scriptSig length =3D x >> >> // x bytes scriptSig >> >> // 4 bytes nSequence >> >> // 1 byte vout count =3D 0x01 >> >> // 8 bytes nValue >> >> // 1 byte scriptPubKey length =3D y >> >> // y bytes scriptPubKey >> >> // 4 bytes nLockTime >> >> // >> >> // Since the fixed overhead is 60 bytes, x + y must equal 4. >> >> if (p[4] !=3D 0x01) { >> >> return false; >> >> } >> >> const unsigned int x =3D p[41]; >> >> switch (x) { >> >> case 0: >> >> if (p[46] !=3D 0x01) return false; >> >> if (p[55] !=3D 0x04) return false; >> >> break; >> >> case 1: >> >> if (p[47] !=3D 0x01) return false; >> >> if (p[56] !=3D 0x03) return false; >> >> break; >> >> case 2: >> >> if (p[48] !=3D 0x01) return false; >> >> if (p[57] !=3D 0x02) return false; >> >> break; >> >> case 3: >> >> if (p[49] !=3D 0x01) return false; >> >> if (p[58] !=3D 0x01) return false; >> >> break; >> >> case 4: >> >> if (p[50] !=3D 0x01) return false; >> >> if (p[59] !=3D 0x00) return false; >> >> break; >> >> default: >> >> return false; >> >> } >> >> const size_t value_pos =3D 47 + x; >> >> const uint64_t raw_value =3D ReadLE64(p + value_pos); >> >> if (raw_value > static_cast(std::numeric_limits::max(= ))) { >> >> return false; >> >> } >> >> const int64_t nValue =3D static_cast(raw_value); >> >> if (!MoneyRange(nValue)) { >> >> return false; >> >> } >> >> return true; >> >> } >> >> static bool IsForbiddenMerkleInternalNode( >> >> const uint256& left, >> >> const uint256& right) >> >> { >> >> unsigned char p[64]; >> >> std::memcpy(p, left.begin(), 32); >> >> std::memcpy(p + 32, right.begin(), 32); >> >> return IsForbiddenMerkleInternalNodePreimage64(p); >> >> } >> >> A Merkle parent computation then checks the preimage before hashing: >> >> static uint256 ComputeMerkleParentChecked( >> >> const uint256& left, >> >> const uint256& right, >> >> bool& invalid) >> >> { >> >> if (IsForbiddenMerkleInternalNode(left, right)) { >> >> invalid =3D true; >> >> return uint256{}; >> >> } >> >> unsigned char p[64]; >> >> std::memcpy(p, left.begin(), 32); >> >> std::memcpy(p + 32, right.begin(), 32); >> >> return Hash(Span(p, 64)); >> >> } >> >> This is the intended minimal rule. It checks the five possible 64-byte o= ne-input, one-output transaction layouts directly. >> >> Miner considerations >> >> Accidental violations by honest miners are expected to be rare. >> >> Adversarial violations are possible. An attacker may grind transaction i= dentifiers so that two transactions, if placed as siblings in the transacti= on Merkle tree, form: >> >> txid_A || txid_B >> >> which encodes a forbidden minimal 64-byte transaction. >> >> An attacker may attempt to influence sibling placement by fee rate, pack= age construction, direct miner submission, or transaction ordering effects. >> >> Therefore miners MUST check candidate block templates before mining. Min= ers MUST NOT rely on accidental violation probability. >> >> Merkle construction failure recovery >> >> If a candidate block template violates this rule, the miner usually does= not need to discard the entire template. The violation is local to one or = more internal Merkle node preimages: >> >> left_child_hash || right_child_hash >> >> A miner can usually repair the candidate block by changing transaction o= rder so that the offending pair of child hashes no longer appears as siblin= gs at the violating Merkle tree level. >> >> Recommended recovery procedure >> >> When Merkle root construction fails because an internal node preimage is= forbidden, mining software SHOULD use the following procedure: >> >> - >> >> Record each offending internal node preimage. >> >> - >> >> Identify the transaction subtree contributing to each offending child ha= sh. >> >> - >> >> Attempt to repair the block by shuffling transaction order while preserv= ing consensus transaction-order constraints. >> >> - >> >> Recompute the Merkle root and re-run the internal-node preimage check. >> >> - >> >> If the shuffled template passes, mine the repaired template. >> >> - >> >> If shuffling fails repeatedly, remove one or more transactions contribut= ing to the offending subtree and rebuild the template. >> >> Preserving transaction-order constraints >> >> A shuffle MUST NOT violate transaction dependency ordering. >> >> If transaction B spends an output created by transaction A in the same b= lock, then A MUST appear before B. >> >> The coinbase transaction MUST remain the first transaction in the block. >> >> Mining software SHOULD shuffle only transactions whose relative order is= not constrained by in-block dependencies, or use a randomized topological = ordering of the block's transaction dependency graph. >> >> Simple shuffle algorithm >> >> A simple repair algorithm is: >> >> 1. Keep the coinbase fixed at index 0. >> >> 2. Build a dependency graph for all non-coinbase transactions. >> >> 3. Generate a randomized topological ordering of the graph. >> >> 4. Construct the Merkle tree using that ordering. >> >> 5. Reject the ordering if any internal node preimage is forbidden. >> >> 6. Retry with a new randomized topological ordering. >> >> This changes Merkle sibling relationships without violating in-block tra= nsaction dependencies. >> >> Repeated failure >> >> If randomized repair fails repeatedly, mining software SHOULD remove tra= nsactions contributing to the repeated offending subtree. >> >> A reasonable policy is: >> >> If Merkle construction fails after 2 independent shuffle attempts, >> >> remove at least one transaction from each repeatedly offending pair or s= ubtree. >> >> For a bottom-level violation, the offending subtree usually corresponds = to two sibling transaction identifiers: >> >> txid_A || txid_B >> >> In that case, the miner may remove either tx_A or tx_B. >> >> For a higher-level violation, each child hash commits to a subtree conta= ining multiple transactions. In that case, the miner may: >> >> 1. Try another dependency-preserving shuffle. >> >> 2. If the same higher-level violation recurs, remove one transaction fro= m one child subtree. >> >> 3. Prefer removing the lowest-feerate removable transaction that does no= t force removal of higher-feerate descendants. >> >> This policy does not need to identify a malicious transaction. It only n= eeds to produce a valid block template with minimal fee loss. >> >> Fee impact >> >> The expected fee impact for honest block templates should be negligible = because accidental violations are rare. >> >> If an adversary intentionally creates transactions that cause violations= when paired, shuffling will usually defeat the attempt without fee loss. I= f shuffling does not repair the template, removing one or more offending tr= ansactions bounds the miner's exposure. >> >> The adversary's practical effect is limited to potentially causing some = transactions to be omitted from a candidate block template. The rule preven= ts upgraded miners from mining invalid blocks, provided miners check the Me= rkle construction before mining. >> >> Relation to unupgraded miners >> >> Because accidental violations are rare, unupgraded miners are unlikely t= o encounter the rule during ordinary operation. >> >> However, an adversary can construct transaction pairs intended to trigge= r the rule under specific sibling placement. >> >> Unupgraded miners that do not enforce this rule may mine a block that up= graded nodes reject after activation. Low accidental probability improves d= eployment safety but is not a substitute for miner enforcement. >> >> Probability analysis >> >> This section estimates accidental violation probability under simplified= randomness assumptions. >> >> Random left || right >> >> Assume the 64-byte internal node preimage is uniformly random. >> >> For the preimage to encode a minimal one-input, one-output 64-byte trans= action, it must satisfy: >> >> vin_count =3D 0x01 >> >> scriptSig_len =3D x, where x =E2=88=88 {0,1,2,3,4} >> >> vout_count =3D 0x01 at the position determined by x >> >> scriptPubKey_len =3D 4 - x >> >> nValue =E2=88=88 [0, MAX_MONEY] >> >> Ignoring nValue, the structural probability is approximately: >> >> 5 / 256^3 >> >> because there are five valid (scriptSig_len, scriptPubKey_len) splits, a= nd three one-byte constraints: >> >> vin_count >> >> vout_count >> >> scriptPubKey_len >> >> Numerically: >> >> 5 / 256^3 =E2=89=88 2.980232238769531e-7 >> >> or approximately: >> >> 1 in 3,355,443 >> >> Including the output value money range: >> >> MAX_MONEY =3D 21,000,000 * 100,000,000 >> >> =3D 2,100,000,000,000,000 >> >> For a uniformly random unsigned 64-bit output value, the probability of = being in range is approximately: >> >> (MAX_MONEY + 1) / 2^64 >> >> =E2=89=88 1.1384122811097797e-4 >> >> Therefore the approximate probability that a random 64-byte preimage is = structurally valid and has an in-range output value is: >> >> (5 / 256^3) * ((MAX_MONEY + 1) / 2^64) >> >> =E2=89=88 3.392733219831406e-11 >> >> or approximately: >> >> 1 in 29,475,000,000 >> >> Random left || left >> >> For an odd-entry duplicated Merkle node, the preimage has the form: >> >> left || left >> >> where the first 32 bytes equal the last 32 bytes. >> >> Let the 32-byte half be: >> >> A[0..31] >> >> Then: >> >> P[0..31] =3D A[0..31] >> >> P[32..63] =3D A[0..31] >> >> For the same one-input, one-output 64-byte transaction shape: >> >> P[4] =3D 0x01 >> >> P[41] =3D scriptSig_len =3D x >> >> P[vout_count_pos] =3D 0x01 >> >> P[scriptpubkey_len_pos] =3D 4 - x >> >> Because positions after byte 31 alias positions in the first half: >> >> P[i] =3D A[i mod 32] >> >> The relevant positions are: >> >> vin_count_pos =3D 4 >> >> script_len_pos =3D 41 =E2=89=A1 9 mod 32 >> >> vout_count_pos =3D 46 + x =E2=89=A1 14 + x mod 32 >> >> scriptpubkey_len_pos =3D 55 + x =E2=89=A1 23 + x mod 32 >> >> The constraints are: >> >> A[4] =3D 0x01 >> >> A[9] =3D x >> >> A[14 + x] =3D 0x01 >> >> A[23 + x] =3D 4 - x >> >> For each fixed x, these are four independent one-byte constraints under = the random-half model. >> >> Thus the structural probability is approximately: >> >> 5 / 256^4 >> >> =E2=89=88 1.1641532182693481e-9 >> >> or approximately: >> >> 1 in 858,993,459 >> >> The output value begins at: >> >> value_pos =3D 47 + x >> >> which aliases to an 8-byte window in the random 32-byte half: >> >> A[15 + x .. 22 + x] >> >> Using the same simplified independence approximation, the probability of= being in MoneyRange is approximately: >> >> (MAX_MONEY + 1) / 2^64 >> >> =E2=89=88 1.1384122811097797e-4 >> >> So the approximate probability that a random left || left preimage is st= ructurally valid and has an in-range output value is: >> >> (5 / 256^4) * ((MAX_MONEY + 1) / 2^64) >> >> =E2=89=88 1.3252864140005492e-13 >> >> or approximately: >> >> 1 in 7,545,600,000,000 >> >> Block-level accidental probability >> >> A block with n transactions has approximately n - 1 internal Merkle node= s, plus duplicated-node cases depending on tree shape. >> >> Using the rough random left || right estimate: >> >> p =E2=89=88 3.39e-11 >> >> A block with 10,000 transactions has approximate accidental violation pr= obability: >> >> 1 - (1 - p)^9999 =E2=89=88 3.39e-7 >> >> or roughly: >> >> 1 in 2,950,000 blocks >> >> This is a simplified estimate. Actual txids are not perfect independent = random samples in all cases, duplicated nodes have lower estimated probabil= ity, and additional implementation details may reduce or alter the rate. >> >> The deployment-relevant conclusion is: >> >> Honest accidental violations should be rare. >> >> Adversarial violations are possible. >> >> Miners must enforce the rule. >> >> Backward compatibility >> >> This is a soft fork. Blocks violating the new rule were previously valid= and become invalid after activation. >> >> Unupgraded full nodes may accept violating blocks after activation. Acti= vation therefore requires ordinary soft-fork deployment procedures. >> >> Unupgraded SPV clients remain vulnerable to the legacy proof ambiguity. = SPV clients must update their Merkle proof validation logic to obtain the b= enefit of this rule. >> >> Test vectors >> >> Test vectors should include: >> >> - >> >> A block whose transaction Merkle internal node preimages do not encode m= inimal 64-byte transactions. The block is valid. >> >> - >> >> A block containing a 64-byte transaction whose serialization does not ap= pear as an internal node preimage. The block is valid. >> >> - >> >> A block where an internal node preimage encodes a minimal 64-byte transa= ction. The block is invalid. >> >> - >> >> A block where an odd-entry duplicated preimage h || h encodes a minimal = 64-byte transaction. The block is invalid. >> >> - >> >> An SPV proof where one branch preimage encodes a minimal 64-byte transac= tion. The proof is rejected. >> >> - >> >> An SPV proof for a 64-byte transaction where no branch preimage encodes = a minimal 64-byte transaction. The proof is accepted if otherwise valid. >> >> Open questions >> >> - >> >> Should the rule include only the explicit minimal 64-byte legacy transac= tion shape above, or should it call the full consensus transaction deserial= izer? >> >> - >> >> Should future transaction serialization changes be required to preserve = this exact forbidden-preimage invariant? >> >> - >> >> Should pre-activation relay policy discourage transaction pairs that can= form forbidden sibling preimages? >> >> - >> >> Should mining software standardize a recovery procedure for failed Merkl= e construction, or should this remain implementation-specific? >> >> - >> >> Should SPV proof formats include an explicit version bit indicating bran= ch-preimage checking support? > > -- > 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= email to bitcoindev+unsubscribe@googlegroups.com. > To view this discussion visit https://groups.google.com/d/msgid/bitcoinde= v/2cae3f35-2058-4e41-8fe9-d2ef06259e0dn%40googlegroups.com. --=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/= gPE88zS-yKekfiQDnkY_gOPqBxo2ExH5CuprnkE0EV0tXUDCmViFlIVhHKokPpcW54dkX26PugR= SwEVja-n9M2mkOiXJAn7HyvygA6V77iA%3D%40protonmail.com. --b1=_ITTgH2aq8BD1AKW8OUVL89oor6hNAUKsfP52PvAXTs Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
It would al= ign with a deployed system. Other deployed systems use differen= t workarounds.

For instance BitVM uses the alternative mitigation also proposed by= Sergio. BitVM's implementation: https://github.com/BitVM/BitVM/pull/295. Sergio's description of the i= dea: https://bitslog.com/2018/08/21/simple-change-to-the-bitcoin-merkleblock-co= mmand-to-protect-from-leaf-node-weakness-in-transaction-merkle-tree/. T= his post notably opens with:
While this solves the problem, it is by no= means a =E2=80=9Cclean=E2=80=9D solution: it=20 creates false-negative cases (with very low probability)  and it reduc= es verification efficiency.

Other bridge= applications check the depth of the proof vs a proof for the coinbase tran= saction: https://github.com/threshold-network/tbtc-v2/blob/cf4d12f71b08511bc21858= 02be88e302b7bef656/solidity/contracts/bridge/BitcoinTx.sol#L194-L197.

More importantly, this is not a good standard by which to judg= e mitigations. The goal of a consensus-enforced mitigation is to make SPV v= erifiers secure without requiring them to implement one of the worka= rounds. Your proposal, besides the substantial costs it would impose on ful= l nodes, does not achieve this goal. Simply invalidating 64-byte transactio= ns does (for all known and non-esoteric imaginable ones).
On Tuesday, June 16th, 2026 at 4:22 PM, jeremy <jeremy.l.rubin@g= mail.com> wrote:
Adding a note & reference that Rootstock uses a simila= r mitigation for it's SPV proofs:

See the below co= de:

https://github.com/rsksm= art/bitcoinj-thin/blob/f89816871d644436e34cd8d0a70c3c8ef41b0836/src/main/ja= va/co/rsk/bitcoinj/core/PartialMerkleTree.java#L187

= And SDL's blog post on the topic: https://bi= tslog.com/2018/06/09/leaf-node-weakness-in-bitcoin-merkle-tree-design


So enforcing this rule would align w= ith existing deployed systems.

On Monday, June 1, 2026 at 2:02:51=E2=80= =AFPM UTC-4 jeremy wrote:

Esteemed Colleagues,

As a result of some of my= research on 64-byte transactions, I'd like to discuss an alternative soft = fork proposal that preserves the ability to encode 64-byte transactions whi= le offering protection to SPV users (who must make a small patch to validat= e the path property).

The rule, stated simply, is:

<= p dir=3D"ltr" style=3D"line-height:1.38;margin:12pt 30pt">A block is inval= id if any Merkle Tree 64-byte preimage has the exact byte structure of a mi= nimal one-input, one-output, witness stripped transaction.

[Wi= th the miracle of GPT,] I've drafted a relatively complete BIP for discussi= on.

Happy International Children's Day,

Jeremy

p.s. I will later propose potentially a couple other mitigations = separately, for discussion as well.


BIP: TBD<= br>Layer: Consensus (soft fork)
Title: Prohibit = Merkle Internal Node Preimages That Encode Minimal 64-Byte Transactions
Author: TBD
Status: Draft
Type: Standards Track
Created: 2026-06-01License: BSD-2-Clause

Abstract

This document specifies a consensus= rule that invalidates a block if any transaction Merkle tree internal node= preimage encodes a minimal 64-byte transaction.

For each inte= rnal Merkle node, Bitcoin computes:

parent =3D SHA256d(left || r= ight)


where left and rig= ht are 32-byte hashes. The 64-byte string left || right is the internal node preimage.

Aft= er activation, a block is invalid if any such 64-byte preimage has the exac= t byte structure of a minimal one-input, one-output, non-witness transactio= n.

This prevents a 64-byte transaction serialization from bein= g malleated into an internal Merkle node preimage in SPV transaction inclus= ion proofs. It does not make 64-byte transactions invalid in general.

Motivation

Bitcoin transaction identifiers and transaction Merkle internal nodes = are both computed with double SHA256:

txid =3D SHA256d(seriali= zed_transaction)

parent =3D SHA256d(left_child_hash || right_chi= ld_hash)


If a v= alid transaction serialization is exactly 64 bytes, the same byte string ca= n also be interpreted as the concatenation of two 32-byte Merkle child hash= es:

serialized_transaction =3D left_child_hash || right_child_ha= sh


This creat= es an ambiguity between a transaction leaf preimage and an internal node pr= eimage.

An SPV verifier that accepts a Merkle proof without au= thenticating the full tree shape can be made to accept a proof terminating = at an internal node rather than at an actual transaction leaf.

= This proposal removes that ambiguity by forbidding Merkle internal node pr= eimages that have the only practical 64-byte transaction encoding shape.

SegWit and transaction iden= tifiers

Since SegWit activation, Bitcoin transactio= ns have two related identifiers:

txid =3D SHA256d(legacy serial= ization)

wtxid =3D SHA256d(witness serialization)

<= b style=3D"font-weight:normal">

The distinction is important = for understanding this proposal.

A SegWit transaction is seria= lized on the wire as:

nVersion

marker

flag=

vin

vout

witness

nLockTime


where:

=

= marker =3D 0x00

flag =3D 0x01


The marker and flag bytes indicate that witnes= s data is present.

However, the transaction identifier (txid) is not computed from this witness seri= alization. Instead, the txid is comput= ed from the legacy serialization:

nVersion

vin=

vout

nLockTime


with the marker, flag, and witness fields omitted.

Therefore:

txid =3D SHA256d(non-witness serialization)


while:

=

= wtxid =3D SHA256d(full witness serialization)


The transaction Merkle root committed in th= e block header is built from transaction identifiers (txids), not witness transaction identifiers (wtxids).

Consequently:

Merkl= e root =3D Merkle(txid_0, txid_1, ..., txid_n)


and not:

Merkle(wtxid_0, wtxid_1= , ..., wtxid_n)


= This means that the marker byte (0x00<= span style=3D"font-size:11pt;font-family:Arial,sans-serif;color:rgb(0,0,0);= background-color:transparent;font-weight:400;font-style:normal;font-variant= :normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">= ), flag byte (
0x01), and witness data = never appear in the transaction Merkle tree committed by the block header.<= /span>

SegWit does define a separate witness Merkle tree whose root i= s committed through the coinbase witness commitment, but that witness Merkl= e tree is distinct from the transaction Merkle tree discussed in this propo= sal.

As a result, the ambiguity addressed by this proposal con= cerns only transaction identifiers (txids) and the transaction Merkle root. The SegWit marker and flag bytes are = irrelevant to the transaction Merkle root because they are excluded from txid serialization.

Minimal 64-byte transaction shape

This proposal is concerned with the serialization used to comp= ute a transaction's txid.

= For legacy transactions, and for SegWit transactions when computing the txid, the serialization format is:

4 bytes nVersion

1 byte vin count =3D 0x01

=

= 36 bytes prevout

1 byte scriptSig length =3D x

x= bytes scriptSig

4 bytes nSequence

1 byte vout= count =3D 0x01

8 bytes nValue

1 byte scriptPub= Key length =3D y

y bytes scriptPubKey

4 bytes nLo= ckTime


Notably,= this serialization does not include:

marker

flag

witness stack


=

because those fields are excluded from = txid computation.

The fixed overhead is:

4 = + 1 + 36 + 1 + 4 + 1 + 8 + 1 + 4 =3D 60 bytes


Therefore, for total serialized size 64:

x + y =3D 4


There are exactly five possible script-length splits:

scrip= tSig length scriptPubKey length

0 4<= /p>

1 3

2 2

3 = 1

4 0


This proposal defines a forbidden Merkle= internal node preimage as a 64-byte byte string satisfying one of those fi= ve layouts and whose single output value is in the consensus money range.

Specification

After activation, a block is invalid if any transaction Merkle = internal node preimage encodes a minimal 64-byte transaction.

<= span style=3D"font-size:11pt;font-family:Arial,sans-serif;color:rgb(0,0,0);= background-color:transparent;font-weight:400;font-style:normal;font-variant= :normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">= For every internal Merkle parent computation in the transaction Merkle tree= :

parent =3D SHA256d(left || right)


where left and right are 32-byte child hashe= s, define:

P =3D left || right


The block is invalid if P satisfies all of the following:

  1. P[4] =3D=3D 0x01= .

  2. P[41] is one = of 0, 1, 2, 3, 4.

  3. Let x =3D P[41].

  4. Let sequence_pos =3D 42 + x.

  5. Let vout_count_pos =3D sequ= ence_pos + 4.

  6. Let value_pos =3D vout_count_pos + 1.

  7. Let scriptpubkey_len_pos =3D value_pos + 8.

  8. <= p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt" r= ole=3D"presentation">P[vout_count_pos] =3D=3D 0x01.

  9. P[scriptpubkey_len_pos] = =3D=3D 4 - x.

  10. Let locktime_pos =3D scriptpubkey_len_pos + 1 + (4 - x).

    <= /li>
  11. locktime_pos + 4 =3D=3D 64.=

  12. The 8-byte little-endian integer at P[value_pos..value_pos+7] is in MoneyRange.

Equivalently, the forbidden= preimage is a 64-byte serialization of a one-input, one-output, non-witnes= s transaction with single-byte CompactSize counts and script lengths, where= the two script lengths sum to 4 and the output value is in range.

For clarity, "non-witness transaction" here refers to the serializatio= n used for txid computation. Even for = SegWit transactions, the transaction Merkle tree uses txids, so the marker byte, flag byte, and witness data are = excluded.

This rule applies to every transaction Merkle intern= al node used to compute the block header's transaction Merkle root.<= /p>

Odd-entry duplication

If a Merkle level has an odd number of entries, Bitcoin dupli= cates the final hash:

parent =3D SHA256d(last || last)


The preimage:

=

= last || last


M= UST be checked by the same rule.

SPV verification rule

An SPV verifier relyi= ng on this soft fork MUST reject a Merkle proof if any branch preimage in t= he proof encodes a minimal 64-byte transaction under the predicate above.

For each branch step, the verifier knows:

  1. The current hash.

    =
  2. The sibling hash.

  3. The branch direction= .

It reconstructs:

P =3D left_child_hash = || right_child_hash


The verifier MUST check:

IsForbiddenMerkleInternalNodePreim= age(P) =3D=3D false


for every branch preimage in the proof.

If any branch pre= image passes the forbidden-preimage predicate, the proof MUST be rejected.<= /span>

The verifier still performs the ordinary Merkle path computati= on and block header proof-of-work validation.

Rationale

The known 64-byte tr= ansaction SPV malleability issue requires a byte string that is both:

a valid 64-byte transaction serialization


and:

a transaction Merkle inter= nal node preimage


=

This proposal forbids that overlap at the Merkle internal node boundary.=

The rule is narrower than invalidating all 64-byte transactio= ns. A 64-byte transaction remains valid unless its exact serialization appe= ars as a transaction Merkle internal node preimage in the same block's tran= saction Merkle tree.

The rule also avoids adding a general tra= nsaction validity rule that exists only to protect Merkle proof semantics.<= /span>

Why SegWit does not elimi= nate the ambiguity

It is sometimes assumed that Seg= Wit automatically removes this ambiguity because SegWit transactions contai= n the marker and flag bytes:

00 01


However, the ambiguity exists at the = txid layer, not at the witness-serialization = layer.

The transaction Merkle root in the block header is comp= uted from txids, and txids are computed from the serialization that excludes= :

marker

flag

witness


Therefore the relevant byte string = remains:

nVersion

vin

vout

nLo= ckTime


exactly = as before SegWit.

The witness serialization affects the wtxid, but the block header's transaction Me= rkle root does not commit to wtxids.

As a result, the existence of the SegWit marker and flag bytes = does not prevent a txid preimage from = having the same byte structure as a Merkle internal node preimage.

The ambiguity addressed by this proposal therefore remains relevant in= the SegWit era.

Contrast= with a 64-byte transaction invalidity rule

A direc= t alternative is:

A transaction is invalid if its serialized siz= e is exactly 64 bytes.


That rule has several advantages:

  1. It is simple to specify.

  2. It is simple for SPV verifiers to implement.

  3. It removes the original ambiguity by eliminating all valid 64-byte tran= saction leaves.

However, it is not correct to descri= be that rule as automatically fixing all light clients.

A 64-b= yte transaction invalidity rule protects an SPV verifier only if the verifi= er enforces the new rule when interpreting the claimed transaction. Existin= g or application-specific SPV verifiers that merely receive a byte string a= nd a Merkle branch may remain vulnerable if they do not parse the claimed t= ransaction and reject exactly-64-byte transaction serializations.

More generally, a consensus rule invalidating 64-byte transactions does= not prevent arbitrary internal node preimages from existing. It only preve= nts those preimages from being valid Bitcoin transactions under upgraded co= nsensus rules. A bridge, wallet, or deposit system that accepts SPV-style p= roofs but performs incomplete transaction parsing may still be induced to t= reat an internal node preimage as an application-level event.

<= span style=3D"font-size:11pt;font-family:Arial,sans-serif;color:rgb(0,0,0);= background-color:transparent;font-weight:400;font-style:normal;font-variant= :normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">= For example, suppose an application-level SPV verifier treats a proved byte= string as a "deposit" if some field inside the alleged transaction matches= a registered deposit address, deposit script, or deposit commitment, but d= oes not fully enforce the upgraded transaction-validity rule. An attacker m= ay be able to grind child hashes so that:

left_child_hash || rig= ht_child_hash


h= as bytes that the application interprets as a deposit transaction or deposi= t commitment. In some systems, the attacker may also be able to choose or r= egister deposit data that matches bytes already present in the left-hand si= de of an internal node preimage.

This is not a failure of upgr= aded full-node consensus. It is a failure of the assumption that changing f= ull-node transaction validity automatically upgrades every SPV verifier and= every bridge, wallet, or application that consumes SPV-style proofs.

Therefore, both approaches require light-client changes:

=

= 64-byte transaction invalidity:

Light clients must reject cla= imed 64-byte transaction serializations.


Merkle-internal-node preimage invalidity:

Light clients must reject proofs containing forbidden internal branch p= reimages.


The= 64-byte transaction invalidity rule is simpler for light clients that corr= ectly implement it, but it is broader at the transaction layer. This propos= al places the rule at the Merkle ambiguity boundary and preserves 64-byte t= ransactions generally.

In summary:

64-byte transact= ion invalidity:

- Simpler SPV rule when implemented correctly.=

- Broader transaction validity change.

- Invali= dates all 64-byte transactions.

- Does not automatically fix S= PV applications that fail to enforce the new rule.


Merkle-internal-node preimage invalidity:=

- Preserves 64-byte transactions generally.

- P= laces the rule at the Merkle ambiguity boundary.

- Requires SP= V verifiers to parse all branch preimages.

- Directly forbid= s the ambiguous internal-node preimage condition.


Minimal C++ implementation sketch

This implementation checks only the minimal forbidden 64-byte s= hape. It does not invoke the full transaction deserializer.

Th= e function returns true if the 64-byte= preimage is forbidden.

static constexpr int64_t COIN =3D 100000= 000;

static constexpr int64_t MAX_MONEY =3D 21000000 * COIN;


static inline bool = MoneyRange(int64_t nValue)

{

return nValue >= =3D 0 && nValue <=3D MAX_MONEY;

}


static inline uint64_t ReadLE64(co= nst unsigned char* p)

{

return uint64_t{p[0]}

| (uint64_t{p[1]} << 8)

| (uint64_= t{p[2]} << 16)

| (uint64_t{p[3]} << 24)

| (uint64_t{p[4]} << 32)

| (uint64_= t{p[5]} << 40)

| (uint64_t{p[6]} << 48)

| (uint64_t{p[7]} << 56);

}


static bool IsForbiddenMerkleInt= ernalNodePreimage64(const unsigned char p[64])

{

= // Minimal 64-byte legacy transaction shape:

//

= // 4 bytes nVersion

// 1 byte vin count =3D 0x01=

// 36 bytes prevout

// 1 byte script= Sig length =3D x

// x bytes scriptSig

/= / 4 bytes nSequence

// 1 byte vout count =3D 0x01

// 8 bytes nValue

// 1 byte scriptPub= Key length =3D y

// y bytes scriptPubKey

= // 4 bytes nLockTime

//

// Since the fi= xed overhead is 60 bytes, x + y must equal 4.


if (p[4] !=3D 0x01) {

r= eturn false;

}

=

const unsigned int x =3D p[41];


switch (x) {

case 0:

if (p[46] !=3D 0x01) return false;

if (p= [55] !=3D 0x04) return false;

break;


case 1:

if (p= [47] !=3D 0x01) return false;

if (p[56] !=3D 0x03) retur= n false;

break;


case 2:

if (p[48] !=3D 0x01) retur= n false;

if (p[57] !=3D 0x02) return false;

= break;


= case 3:

if (p[49] !=3D 0x01) return false;

= if (p[58] !=3D 0x01) return false;

break;<= /p>


case 4:

= if (p[50] !=3D 0x01) return false;

if (p[59] !=3D= 0x00) return false;

break;


default:

return fals= e;

}


const size_t value_pos =3D 47 + x;

const uint64_t raw= _value =3D ReadLE64(p + value_pos);


if (raw_value > static_cast<uint64_t>(std::= numeric_limits<int64_t>::max())) {

return false;

}


= const int64_t nValue =3D static_cast<int64_t>(raw_value);


if (!MoneyRange(nValu= e)) {

return false;

}


return true;

}=


static bool IsForbidden= MerkleInternalNode(

const uint256& left,

= const uint256& right)

{

unsigned char p[64];<= /span>


std::memcpy(p= , left.begin(), 32);

std::memcpy(p + 32, right.begin(), 32);=


return IsFor= biddenMerkleInternalNodePreimage64(p);

}


A Merkle parent computation then che= cks the preimage before hashing:

static uint256 ComputeMerklePar= entChecked(

const uint256& left,

const = uint256& right,

bool& invalid)

{

if (IsForbiddenMerkleInternalNode(left, right)) {

= invalid =3D true;

return uint256{};

}=


unsigned cha= r p[64];

std::memcpy(p, left.begin(), 32);

s= td::memcpy(p + 32, right.begin(), 32);


return Hash(Span<const unsigned char>(p, 64= ));

}


<= p dir=3D"ltr" style=3D"line-height:1.38;margin-top:12pt;margin-bottom:12pt"= >This is the intended minimal rule. It checks the five possible 64-byte on= e-input, one-output transaction layouts directly.

Miner considerations

Acc= idental violations by honest miners are expected to be rare.

A= dversarial violations are possible. An attacker may grind transaction ident= ifiers so that two transactions, if placed as siblings in the transaction M= erkle tree, form:

txid_A || txid_B


which encodes a forbidden minimal 64-byte tr= ansaction.

An attacker may attempt to influence sibling placem= ent by fee rate, package construction, direct miner submission, or transact= ion ordering effects.

Therefore miners MUST check candidate bl= ock templates before mining. Miners MUST NOT rely on accidental violation p= robability.

Merkle constr= uction failure recovery

If a candidate block templa= te violates this rule, the miner usually does not need to discard the entir= e template. The violation is local to one or more internal Merkle node prei= mages:

left_child_hash || right_child_hash


A miner can usually repair the candi= date block by changing transaction order so that the offending pair of chil= d hashes no longer appears as siblings at the violating Merkle tree level.<= /span>

Recommended recovery proc= edure

When Merkle root construction fails because a= n internal node preimage is forbidden, mining software SHOULD use the follo= wing procedure:

    Record each offending internal node preimage.

  1. Identify the transaction subtree contributing to each offending child ha= sh.

  2. Attempt to repair the block by shuffling transac= tion order while preserving consensus transaction-order constraints.=

  3. Recompute the Merkle root and re-run the internal-node p= reimage check.

  4. If the shuffled template passes, mine= the repaired template.

  5. If shuffling fails repeated= ly, remove one or more transactions contributing to the offending subtree a= nd rebuild the template.

Preserving transaction-order constraints

<= span style=3D"font-size:11pt;font-family:Arial,sans-serif;color:rgb(0,0,0);= background-color:transparent;font-weight:400;font-style:normal;font-variant= :normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">= A shuffle MUST NOT violate transaction dependency ordering.

If= transaction B spends an output create= d by transaction A in the same block, = then A MUST appear before B.

The coinbase transaction MUST rema= in the first transaction in the block.

Mining software SHOULD = shuffle only transactions whose relative order is not constrained by in-blo= ck dependencies, or use a randomized topological ordering of the block's tr= ansaction dependency graph.

Simple shuffle algorithm

A simple repair algorit= hm is:

1. Keep the coinbase fixed at index 0.

2. Bu= ild a dependency graph for all non-coinbase transactions.

3. Ge= nerate a randomized topological ordering of the graph.

4. Constr= uct the Merkle tree using that ordering.

5. Reject the ordering = if any internal node preimage is forbidden.

6. Retry with a new= randomized topological ordering.


This changes Merkle sibling relationships without violat= ing in-block transaction dependencies.

Repeated failure

If randomized repair= fails repeatedly, mining software SHOULD remove transactions contributing = to the repeated offending subtree.

A reasonable policy is:

If Merkle construction fails after 2 independent shuffle attempts,<= /span>

remove at least one transaction from each repeatedly offending p= air or subtree.


= For a bottom-level violation, the offending subtree usually corresponds to= two sibling transaction identifiers:

txid_A || txid_B


In that case, the miner = may remove either tx_A or tx_B.

For a higher-level violation, e= ach child hash commits to a subtree containing multiple transactions. In th= at case, the miner may:

1. Try another dependency-preserving shu= ffle.

2. If the same higher-level violation recurs, remove one t= ransaction from one child subtree.

3. Prefer removing the lowest= -feerate removable transaction that does not force removal of higher-feerat= e descendants.


<= span style=3D"font-size:11pt;font-family:Arial,sans-serif;color:rgb(0,0,0);= background-color:transparent;font-weight:400;font-style:normal;font-variant= :normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">= This policy does not need to identify a malicious transaction. It only need= s to produce a valid block template with minimal fee loss.

Fee impact

The ex= pected fee impact for honest block templates should be negligible because a= ccidental violations are rare.

If an adversary intentionally c= reates transactions that cause violations when paired, shuffling will usual= ly defeat the attempt without fee loss. If shuffling does not repair the te= mplate, removing one or more offending transactions bounds the miner's expo= sure.

The adversary's practical effect is limited to potential= ly causing some transactions to be omitted from a candidate block template.= The rule prevents upgraded miners from mining invalid blocks, provided min= ers check the Merkle construction before mining.

Relation to unupgraded miners

=

Because accidental violations are rare, unupgraded miners are unlikely t= o encounter the rule during ordinary operation.

However, an ad= versary can construct transaction pairs intended to trigger the rule under = specific sibling placement.

Unupgraded miners that do not enfo= rce this rule may mine a block that upgraded nodes reject after activation.= Low accidental probability improves deployment safety but is not a substit= ute for miner enforcement.

Probability analysis

This section estimates accid= ental violation probability under simplified randomness assumptions.=

Random left || right

Assume the 64-byte internal node= preimage is uniformly random.

For the preimage to encode a mi= nimal one-input, one-output 64-byte transaction, it must satisfy:

vin_count =3D 0x01

scriptSig_len =3D x, where x =E2=88=88 {0,1= ,2,3,4}

vout_count =3D 0x01 at the position determined by x

scriptPubKey_len =3D 4 - x

nValue =E2=88=88 [0, MAX_MONEY= ]


Ignoring nValue, the structural probability is appr= oximately:

5 / 256^3


because there are five valid = (scriptSig_len, scriptPubKey_len) splits, and three one-byte constr= aints:

vin_count

vout_count

scriptPubKey_l= en


Numericall= y:

5 / 256^3 =E2=89=88 2.980232238769531e-7


or approximately:

1 in = 3,355,443


Inc= luding the output value money range:

MAX_MONEY =3D 21,000,000 * = 100,000,000

=3D 2,100,000,000,000,000


For a uniformly random unsigned= 64-bit output value, the probability of being in range is approximately:

(MAX_MONEY + 1) / 2^64

=E2=89=88 1.1384122811097797e-4=


Therefore the = approximate probability that a random 64-byte preimage is structurally vali= d and has an in-range output value is:

(5 / 256^3) * ((MAX_MONEY= + 1) / 2^64)

=E2=89=88 3.392733219831406e-11


or approximately:

1 in= 29,475,000,000


Rand= om left || left

For an= odd-entry duplicated Merkle node, the preimage has the form:

le= ft || left


whe= re the first 32 bytes equal the last 32 bytes.

Let the 32-byte= half be:

A[0..31]

=

Then:

P[0..31] =3D A[0..31]

P[32..63]= =3D A[0..31]


F= or the same one-input, one-output 64-byte transaction shape:

P[4= ] =3D 0x01

P[41] =3D scriptSig_len =3D x

P[vout_cou= nt_pos] =3D 0x01

P[scriptpubkey_len_pos] =3D 4 - x

=

Because positions after byte= 31 alias positions in the first half:

P[i] =3D A[i mod 32]


The relevant posi= tions are:

vin_count_pos =3D 4

script_len_pos = =3D 41 =E2=89=A1 9 mod 32

vout_count_pos =3D 4= 6 + x =E2=89=A1 14 + x mod 32

scriptpubkey_len_pos =3D 55 + x = =E2=89=A1 23 + x mod 32


The constraints are:

A[4] =3D 0x01

A[9]= =3D x

A[14 + x] =3D 0x01

A[23 + x] =3D 4 - x


For each fixed x, these are four independent one-byte c= onstraints under the random-half model.

Thus the structural pr= obability is approximately:

5 / 256^4

=E2=89=88 1.164= 1532182693481e-9


<= p dir=3D"ltr" style=3D"line-height:1.38;margin-top:12pt;margin-bottom:12pt"= >or approximately:

1 in 858,993,459


The output value begins at:

val= ue_pos =3D 47 + x


=

which aliases to an 8-byte window in the random 32-byte half:

=

= A[15 + x .. 22 + x]


<= /p>

Using the same simplified independence approximation, the probability= of being in MoneyRange is approximate= ly:

(MAX_MONEY + 1) / 2^64

=E2=89=88 1.13841228110977= 97e-4


So the ap= proximate probability that a random left || le= ft preimage is structurally valid and has an in-range output value = is:

(5 / 256^4) * ((MAX_MONEY + 1) / 2^64)

=E2=89=88 = 1.3252864140005492e-13


or approximately:

1 in 7,545,600,000,000


Block-level accidental probability

A block with n = transactions has approximately n - 1 i= nternal Merkle nodes, plus duplicated-node cases depending on tree shape.

Using the rough random left || rig= ht estimate:

p =E2=89=88 3.39e-11


A block with 10,000 transactions has= approximate accidental violation probability:

1 - (1 - p)^9999 = =E2=89=88 3.39e-7


=

or roughly:

1 in 2,950,000 blocks


This is a simplified estimate. Actual txid= s are not perfect independent random samples in all cases, duplicated nodes= have lower estimated probability, and additional implementation details ma= y reduce or alter the rate.

The deployment-relevant conclusion= is:

Honest accidental violations should be rare.

Adv= ersarial violations are possible.

Miners must enforce the rule.<= /span>


Backward compatibilit= y

This is a soft fork. Blocks violating the new rul= e were previously valid and become invalid after activation.

U= nupgraded full nodes may accept violating blocks after activation. Activati= on therefore requires ordinary soft-fork deployment procedures.

<= p dir=3D"ltr" style=3D"line-height:1.38;margin-top:12pt;margin-bottom:12pt"= >Unupgraded SPV clients remain vulnerable to the legacy proof ambiguity. S= PV clients must update their Merkle proof validation logic to obtain the be= nefit of this rule.

Test= vectors

Test vectors should include:

  • A block whose transact= ion Merkle internal node preimages do not encode minimal 64-byte transactio= ns. The block is valid.

  • A block containing a 64-byte= transaction whose serialization does not appear as an internal node preima= ge. The block is valid.

  • A block where an internal no= de preimage encodes a minimal 64-byte transaction. The block is invalid.

  • A block where an odd-entry duplicated preimage = h || h encodes a minimal 64-byte transaction.= The block is invalid.

  • An SPV proof where one branch= preimage encodes a minimal 64-byte transaction. The proof is rejected.

  • An SPV proof for a 64-byte transaction where no branch= preimage encodes a minimal 64-byte transaction. The proof is accepted if o= therwise valid.

  • = Open questions

    1. Should the rule include only the explicit minimal 64-byt= e legacy transaction shape above, or should it call the full consensus tran= saction deserializer?

    2. Should future transaction seri= alization changes be required to preserve this exact forbidden-preimage inv= ariant?

    3. Should pre-activation relay policy discourag= e transaction pairs that can form forbidden sibling preimages?

    4. Should mining software standardize a recovery procedure for fail= ed Merkle construction, or should this remain implementation-specific?

    5. Should SPV proof formats include an explicit version bi= t indicating branch-preimage checking support?

    --
    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+u= nsubscribe@googlegroups.com.
    To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/2cae3f35-2058-4e41-8f= e9-d2ef06259e0dn%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/bitcoindev/= gPE88zS-yKekfiQDnkY_gOPqBxo2ExH5CuprnkE0EV0tXUDCmViFlIVhHKokPpcW54dkX26PugR= SwEVja-n9M2mkOiXJAn7HyvygA6V77iA%3D%40protonmail.com.
    --b1=_ITTgH2aq8BD1AKW8OUVL89oor6hNAUKsfP52PvAXTs--