Return-Path: Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 67BBBC0037 for ; Sat, 27 Jan 2024 07:26:05 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 2F21F41FDC for ; Sat, 27 Jan 2024 07:26:05 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 2F21F41FDC Authentication-Results: smtp4.osuosl.org; dkim=pass (2048-bit key, unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=ZpPMxnOt X-Virus-Scanned: amavisd-new at osuosl.org X-Spam-Flag: NO X-Spam-Score: -2.6 X-Spam-Level: X-Spam-Status: No, score=-2.6 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id XtgKcUCMOayG for ; Sat, 27 Jan 2024 07:26:02 +0000 (UTC) X-Greylist: delayed 392 seconds by postgrey-1.37 at util1.osuosl.org; Sat, 27 Jan 2024 07:26:01 UTC DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org E794241FCE Received: from fhigh6-smtp.messagingengine.com (fhigh6-smtp.messagingengine.com [103.168.172.157]) by smtp4.osuosl.org (Postfix) with ESMTPS id E794241FCE for ; Sat, 27 Jan 2024 07:26:01 +0000 (UTC) Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailfhigh.nyi.internal (Postfix) with ESMTP id 4479211400A6; Sat, 27 Jan 2024 02:19:28 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute2.internal (MEProxy); Sat, 27 Jan 2024 02:19:28 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; t=1706339968; x=1706426368; bh=Txrnwp9TZqOsShXJbynyaKYkf2O8 2cInzGm+k3oGMnQ=; b=ZpPMxnOtU3/wjuZdepZW3G9Qy9mQxlRnZtxwyAB1/6FQ vueOGAHMoE1IRAetWSYAScmq+2cBw29j0MH6jjFzeV2bKIXnMlUFkpF6EWqWQlXG cxr6dv8qagvCTM5kuWaO+mOgLs84oyVZueNUyGDcVHnwJpZruZyeliRraDuLzlVu 44lvKxq95FfUH/QnPsy+BVh04QGml27PTemk4mmsX7LI3SEUcMYRM0OKWXe7GaHV tTszSBKOZHTFmYPIrGP2NgjcyMRN6aC9jpmvIojwRz4rJ7sJtx0RIz5Cfnb0n5qK sOlW2/YcPiEBmoGrQ1IIGxtXWiNaB/yUrCd/uWZoTw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvkedrvdelkedguddtgecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecunecujfgurhepfffhvffukfhfgggtuggjsehgtd erredttdejnecuhfhrohhmpefrvghtvghrucfvohguugcuoehpvghtvgesphgvthgvrhht ohguugdrohhrgheqnecuggftrfgrthhtvghrnhepledtteevueevhfdvfeevfeevffehud fhffetgeehtddtvefgveejteevjeevjefhnecuffhomhgrihhnpehpvghtvghrthhouggu rdhorhhgpdhsthgrtghkvghrrdhnvgifshdpghgvthhnvgifrgguughrvghsshdrthhone cuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepphgvthgv sehpvghtvghrthhouggurdhorhhg X-ME-Proxy: Feedback-ID: i525146e8:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sat, 27 Jan 2024 02:19:26 -0500 (EST) Received: by localhost (Postfix, from userid 1000) id A20E75F84B; Sat, 27 Jan 2024 07:19:22 +0000 (UTC) Date: Sat, 27 Jan 2024 07:19:22 +0000 From: Peter Todd To: Murch , Bitcoin Protocol Discussion Message-ID: References: <9a89eca8-61fd-4156-825d-c9b718dc3034@murch.one> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="+FlKIbswhidnlpem" Content-Disposition: inline In-Reply-To: <9a89eca8-61fd-4156-825d-c9b718dc3034@murch.one> Subject: Re: [bitcoin-dev] One-Shot Replace-By-Fee-Rate X-BeenThere: bitcoin-dev@lists.linuxfoundation.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Bitcoin Protocol Discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 27 Jan 2024 07:26:05 -0000 --+FlKIbswhidnlpem Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Mon, Jan 22, 2024 at 01:12:45PM -0500, Murch via bitcoin-dev wrote: > Hi Peter, >=20 > On 1/18/24 13:23, Peter Todd via bitcoin-dev wrote: > > Reposting this blog post here for discussion: > > > > https://petertodd.org/2024/one-shot-replace-by-fee-rate >=20 > I saw your proposal mentioned on Stacker News and read it with interest. = In > response, I described a replacement cycle that can be used to broadcast t= he > same five transactions repeatedly: >=20 > https://stacker.news/items/393182 >=20 > The gist is that by using two confirmed inputs and five transactions, you > can use RBFr to reduce the absolute fee while raising the feerate to top > block levels, then immediately use the current RBF rules to introduce a > high-feerate transaction that beats the RBFr transaction but is hampered = by > a low-feerate parent and not attractive for mining, then use RBF to repla= ce > its low-feerate parent, then use the RBFr transaction again to reduce the > absolute feerate. Due to the asymmetric replacements, the same transactio= ns > can replace each other in that order in every cycle. Please refer to the > linked write-up for details, I=E2=80=99ve included weights, fees, and a t= ransaction > graph to make my example comprehensible. >=20 > Among those five transactions, the only transaction attractive for block > inclusion would be the small RBFr transaction with a > bottom-of-the-next-block feerate. Today, if it were mined it would amount= to > fees of around 4000 sats every few blocks to make the entire network relay > transactions of more than 205,000=E2=80=AFvB every few seconds. Given tha= t my > example is minimal, it should be possible to further increase bandwidth > cost. >=20 > Assuming that I did not make a mistake, i.e. all the replacements are via= ble > and my scenario is compatible with your proposal, the described One-Shot > Replace-By-Fee-Rate proposal would not be safe for deployment on the > network. I actually tried this attack out, and it fails at step #4 due to the Rule #= 6, PaysMoreThanConflicts, check. While on stacker.news you stated that: tx_HS has 5000 vB and pays 21 s/vB, but since it spends an output from a low-feerate parent, it=E2=80=99s mining score is only 1.95=E2=80=AFs/vB. and You RBF tx_LL and tx_HS with tx_LM that has 100,000 vB and pays 3.05=E2= =80=AFs/vB (fee: 305,000 s) by spending the outputs C1 and C2. This is permitted, since = only tx_LL is a direct conflict, so the feerate of tx_HS does not have to be= beat directly. tx_HS _is_ considered to be a direct conflict, and its raw fee-rate _does_ = have to be beat directly. While ts_HS does spend an unconfirmed output, it appea= rs that the fee-rate PaysMoreThanConflicts uses to calculate if ts_HS can be beaten is ts_HS's raw fee-rate. So looks like your understanding was incorr= ect on these two points. FYI here is the actual test script I used to test this attack. You can run = it using Bitcoin v26.0 with the -acceptnonstdtxn -mempoolfullrbf=3D1 command l= ine arguments, with python-bitcoinlib v0.12.2 installed. #!/usr/bin/env python3 import bitcoin bitcoin.SelectParams('regtest') import bitcoin.rpc import sys =66rom bitcoin.core import * =66rom bitcoin.core.script import * =66rom bitcoin.wallet import * proxy =3D bitcoin.rpc.Proxy() my_addr =3D proxy.getnewaddress().to_scriptPubKey() coins =3D proxy.listunspent(1) print(coins[0:2]) txo1 =3D coins[0]['outpoint'] txo1_amount =3D coins[0]['amount'] txo2 =3D coins[1]['outpoint'] txo2_amount =3D coins[1]['amount'] print(txo1) print(txo2) for i in range(0, 1): # Step 2 tx_ll =3D CTransaction( [CTxIn(txo1)], [CTxOut(txo1_amount - 100000, my_addr), CTxOut(0, CScript([OP_RETURN, b'x' * 90000]))]) r =3D proxy.signrawtransactionwithwallet(tx_ll) assert(r['complete']) tx_ll_signed =3D r['tx'] print('tx_ll =3D %s' % b2lx(proxy.sendrawtransaction(tx_ll_signed))) tx_ls =3D CTransaction( [CTxIn(COutPoint(tx_ll.GetTxid(), 0))], [CTxOut(txo1_amount - 100000 - 300, my_addr)]) r =3D proxy.signrawtransactionwithwallet(tx_ls) assert(r['complete']) tx_ls_signed =3D r['tx'] print('tx_ls =3D %s' % b2lx(proxy.sendrawtransaction(tx_ls_signed))) # Step 3 tx_hs =3D CTransaction( [CTxIn(COutPoint(tx_ll.GetTxid(), 0)), CTxIn(txo2)], [CTxOut((txo1_amount - 100000) + txo2_amount - 4000, my_addr)]) r =3D proxy.signrawtransactionwithwallet(tx_hs) assert(r['complete']) tx_hs_signed =3D r['tx'] print('tx_hs =3D %s ' % b2lx(proxy.sendrawtransaction(tx_hs_signed))) # Step 4 tx_lm =3D CTransaction( [CTxIn(txo1), CTxIn(txo2)], [CTxOut(txo1_amount + txo2_amount - 300000, my_addr), CTxOut(0, CScript([OP_RETURN, b'x' * 90000]))]) r =3D proxy.signrawtransactionwithwallet(tx_lm) assert(r['complete']) tx_lm_signed =3D r['tx'] print('tx_lm =3D %s' % b2lx(proxy.sendrawtransaction(tx_lm_signed))) --+FlKIbswhidnlpem Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEE0RcYcKRzsEwFZ3N5Lly11TVRLzcFAmW0rnkACgkQLly11TVR LzdVzg/+KPUkIvZNF9cqBmRx32tfxehFlqaLZoBqAS2YGEhKbX1QoCFwM8R7F2VM pP/16pJeZszRDrbo8dk3/X5r4qpDQfpv2Q748+DbxtYMTBngkXJgdaYX1Vi2RtzA 7lGrN930Grw7IqHGGD1yp5S7rqk/tggP6Kux/mvsS0/Ntg7SQeVTqbfSFLEfLBVj lr65B3IUb3m8PsBm4xdLVjZIVYnJqTCBmBDgm6tnw9hiEOCbkZhn7hIBrLJ0NJLR xpUUW7XFx/+wvtntZphVBeKo89z7RohP5acRsFY5hFw+hCt7AlCNVH5Rd9n3yvj8 uRR9y8znMC/sw/1DR7fWV1mC0y338IaN4fuABnocLyMtk2mcVAmATB5xhiIFO9f4 LxYjqi10ybcgcE/6zGH/IcMEE0chUKH/2ySM+hu2RnkCuWx+1pnUeqoE+7Ij4H8u LvVixbqabTRlAKAunoRzLjdUZ4XHRguoplwxLLZIGUicaMjQBVFMd4x0mPhuryJQ 11GOhQ3Nu7xtuEZDjlrTZYLZ8JinlSeP0pIO2LZgqsX6FO0LQduuajGxTeHdm/IQ eQMrr7lsTKKBbjSgODGUS9uhP5dCAIM1nawW3ScOnBXiNYp97S5wWdcNiUrxmM4i QLYPtKMG5kF86lky5ayuzfL1Wwbbcfzy2rJ4WognZf/fF4SLld4= =ygyc -----END PGP SIGNATURE----- --+FlKIbswhidnlpem--