On April, I was working on adding some stats based on logs about compact block reconstruction in peer-observer (see 420 and 465), since then, I’ve been looking to the added panels to validate them and I’ve seen some degradation around one of them: Compact block reconstruction without transaction requests per day.
In a simple way, ideally, when a block is mined and someone relay it to us, we’d have all transactions on our mempool. The sender send us a set of short ids of each transaction in that block instead of the full raw version of it, saving some bytes. If we don’t have one of the transactions, we ask the sender for them to be able to reconstruct the full block – a roundtrip that ideally wouldn’t happen. See BIP-152 for more details.
Example of a reconstruction log:
2026-04-06T15:02:09.404125Z [cmpctblock] Successfully reconstructed block 000000...6b6ad5
with 1 txn prefilled,
2714 txn from mempool (incl at least 2 from extra pool)
and 4 txn (886 bytes) requested
I broke some lines to help reading, but it’s just a single line. This log tells us that: 1 transaction came prefilled, coinbase always comes prefilled as probably we wouldn’t have; 2714 were in our mempool and 2 of them were in extrapool, this extra acts like a “pre-discard”, instead of simply erasing it from the mempool, we keep it for some time; and the focus of this post, 4 transactions requested, this causes the roundtrip, making us send a getblocktxn to the sender.
The degradation
The below image shows how much reconstructions requested zero transactions from the sender, based on the previous log. Higher is better.
It shows a clear degradation in this metric from 2026-07-18 to 2026-10-18, from around 35~60% to at most 10% inside the period. This can be also seen in b10c’s nodes as the below image shows, see delving#1052 tables for a longer period.
What does it mean for the network? More roundtrips happening in reconstructions, so more getblocktxn being sent from nodes when (ideally) it shouldn’t happen – among other problems of network.
For a very long time, as a newbie in bitcoin, I had no idea of what could be causing this. But I recently read some posts/comments that opened a great hypothesis for this.
/p2aburn.*/
After reading #193, I took some time investigating those strange agents: /Sat0shi:31.0.0/ and /Satoshi:31.0.0/ with protocol version 70015. I also found another agent behaving similarly /p2aburn.*/, that was also mentioned later in the same post. Later, I found /txbroadcast.*/ which also behaves similarly to those peers.
The moment those nodes first appear seems to correlate with the degradation start and they make sense to impact on this. As mentioned by the author, and also seen on my node, they were sending many unsolicited transactions to our nodes.
At #193 comment, I built a first timeline with each event, but here it is a more updated version:
The bar panels are based on logs and they go from now until 2026-07-08.
The query used for the peer-observer data (line panels) is sum by (useragent) (increase(peerobserver_p2p_version_useragent{useragent=~"/txbroadcast.*|/p2aburn.*|/Sat0shi:31.0.0/"}[1d])). Also, it doesn’t mean that they held X connections on that day.
There’s no way to filter Satoshi:31.0.0 70015 in peer-observer data, but they appear on the panel based on logs.
Timeline:
2026-07-03: /p2aburn-probe:0.1/ first appearance;
2026-07-04: /txbroadcast:0.1/ first appearance;
2026-07-07: a single /p2aburn:0.1/ connection;
2026-07-14: /p2aburn:1.0/ first appearance;
2026-07-18: compact block reconstruction degradation starts (below 10% from 2026-07-23);
2026-07-25: /txbroadcast:0.1/ last appearance;
2026-07-28: /Sat0shi:31.0.0/ first appearance;
2026-09-21: /Satoshi:31.0.0/ (protocol 70015) first appearance;
2026-09-22: /Sat0shi:31.0.0/ last appearance;
2026-10-18: /Satoshi:31.0.0/ (protocol 70015) last appearance;
2026-10-19: after some peaks, /p2aburn:1.0/ falls to about 30~50 connections per day and a very low volume of messages.
At the same time that /p2aburn:1.0/ arrived and started sending a meaningful volume of messages, the metric started declining. And just recently, since many VPS providers rebooted their machines due to CVE-2026-99999 (including mine), see more at #189, this metric bumped to the usual 40~60%. This may have another reasons, but at the moment is my only clue on why they’ve stopped.
Note: from now on, I will call /txbroadcast:0.1/, /Sat0shi:31.0.0/ and /Satoshi:31.0.0/ (protocol 70015) set as the “fleet” – because their behavior are similar, unlike /p2aburn.*/.
Currently, we have zero connections to the fleet and just a few /p2aburn.*/ active, but sending a way lower volume of messages.
Also, see how much tx messages they were sending to my node (based on logs, until 2026-07-08):
For this specific section, most part of it was written by a llm checking my data/logs, it seems to make sense with all the data I’ve seen.
The “fleet” (builds the chains)
It pushes transactions without announcing them. We received 32.9M tx messages from it against only 1.8M inv. A normal peer announces with inv and sends the transaction only when asked. At its peak (Oct 5) it sent ~1.33M transactions a day.
It reconnects constantly. We saw ~31.7k handshakes over the period.
It builds P2A chains carrying Runes:
A root transaction, funded by a wallet input, creates an anchor (290 sats in the chain we followed; other roots use 280, 350 and so on).
Each link spends the previous anchor, pays 10 sats of fee and creates an anchor 10 sats smaller.
When the anchor reaches 240 sats (the dust limit), a refill transaction tops it up again.
A closing transaction pays 679 sats of fee and ends the chain.
Each link mints 1 unit of rune 1:0. Under the mint rule, the runes accumulate on the anchor until the closing transaction.
p2aburn (breaks the chains)
It says the bare minimum. We received only tx (2.96M), pong, version and verack from it. It never sends inv, ping, addr or headers, so it does not announce anything either: it just pushes transactions.
It reconnects a lot. We saw 28,770 handshakes, close to 3k a day at the peak (Oct 17).
It sweeps anchors. Each of its transactions spends an anchor in the middle of a fleet chain and turns the anchor’s whole value into fee. The verified example is sweeper 0b88a628...: 66 vB, 290 sats of fee, and it replaced links 1 to 4 in our mempool. Its average transaction size, ~66 to 80 bytes, fits this. Under the Runes mint rule, a sweep would also burn the runes accumulated on the anchor. That part is inferred: we never decoded a sweeper.
It was already sending transactions on Jul 22, a week before the fleet showed up. We don’t know what it was sweeping then.
It almost stopped after Oct 18. The following days saw ~150 transactions and ~40 connections a day, against 69k transactions on Oct 17. That fits: it ran out of chains to sweep.
The transaction chains
A transaction can spend an output of another transaction that is not confirmed yet. Doing this repeatedly gives a chain: tx1 is in the mempool, tx2 spends tx1’s output, tx3 spends tx2’s, and so on. A miner can include the whole chain in one block, as long as each link comes after its parent.
The “fleet” builds these chains on top of P2A (pay-to-anchor) outputs. A P2A output has a 4-byte script and no key: anyone can spend it without a signature, and the input is the smallest there is (41 vB). Each link in the fleet’s chains:
spends the P2A anchor created by the previous link;
creates a new anchor 10 sats smaller than the one it spends (from 290 down to 240, the dust limit), and a closing tx sweeps the last anchor with a wallet input, paying 679 sats;
carries a Runes OP_RETURN;
is 94 to 107 bytes and pays 10 sats of fee (~0.1 sat/vB).
The chains are up to 25 links long. Since there is no key, the fleet can build and broadcast whole chains very fast. The flip side is that the same property lets anyone spend an anchor in the middle of a chain.
Those 25 txs clusters are very common to be in mempool, take a look at the below metric taken out of Cluster Mempool Observer histogram. Btw it’s a personal project to track a history of every movement of the mempool and its clusters (still experimental). Here you can look at many examples of them individually, and here you can see them in mempool space.
Also those “Rune mint chains” possibility is mentioned at delving#1052.
How a mid-chain replacement could degrade compact block reconstruction
I personally didn’t know much about P2A, tried to learn a bit about it. Feel free to correct me if I say anything wrong.
This is my main hypothesis right now, since a single transaction is all that’s need to trigger a getblocktxn in reconstruction, I think this can be great part of the reason why we see this degradation.
Anyone who gets a conflicting spend of one link into the mempool can cut a chain of unconfirmed transactions. For example:
A chain of 10 transactions, tx1 to tx10, each spending an output of the previous one.
Someone broadcasts tx5’, which spends the same input as tx5 and pays a higher fee.
My node correctly accepts tx5’ under the RBF rules and evicts tx5 along with its descendants, tx6 to tx10. If tx5’ arrives first, the node rejects tx5 instead, and tx6 to tx10 never get in because their inputs are missing.
A miner that has the original chain and never takes tx5’ mines all 10.
When the block arrives, my node is missing tx5 to tx10. It cannot rebuild the block from the compact block alone and has to fetch them with getblocktxn. Bitcoin Core keeps recently replaced transactions in extrapool for this case, but at high enough volume they no longer fit.
My node did nothing wrong at any step. Its mempool holds a valid history that differs from the one the miner chose.
Cost
With plain RBF, the replacement must pay more in absolute fees than everything it evicts. It costs nothing only when it never confirms, which is what happens in the example: the block containing the original chain invalidates it. If a miner picks up tx5’ instead, the sender pays.
P2A anchors remove most of that cost. Because anyone can spend an anchor, the sweeper’s fee comes almost entirely from the anchor’s own value. In what I saw, a sweeper spends an anchor and turns its whole value into fee (290 sats for the root anchor), so the sender adds nothing of their own.
In this case, my node already have the rest of the chain, so it rejected the sweeper, but later a miner mined the sweeper.
fada93...89b log history
# sweeper fada93f79fdfd38ffd9049ffe61195e858b5b110fdffefa16f1440a62078e89b and its parent 9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788
2026-10-13T05:45:50.736096Z \[validation\] Enqueuing TransactionAddedToMempool: txid=9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788 wtxid=265a8c7dad0c3e0fb0329777c279aab78b031b149333357ec3fade3ec42d7c4f
2026-10-13T05:45:50.736226Z \[mempool\] AcceptToMemoryPool: peer=492350: accepted 9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788 (wtxid=265a8c7dad0c3e0fb0329777c279aab78b031b149333357ec3fade3ec42d7c4f) (poolsz 80331 txn, 219945 kB)
2026-10-13T05:45:50.736435Z \[validation\] TransactionAddedToMempool: txid=9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788 wtxid=265a8c7dad0c3e0fb0329777c279aab78b031b149333357ec3fade3ec42d7c4f
2026-10-13T05:45:50.882843Z \[mempoolrej\] fada93f79fdfd38ffd9049ffe61195e858b5b110fdffefa16f1440a62078e89b (wtxid=fada93f79fdfd38ffd9049ffe61195e858b5b110fdffefa16f1440a62078e89b) from peer=491503 was not accepted: insufficient fee, rejecting replacement fada93f79fdfd38ffd9049ffe61195e858b5b110fdffefa16f1440a62078e89b, not enough additional fees to relay; 0.00 < 0.00000007
2026-10-13T05:45:50.882883Z \[txpackages\] tx fada93f79fdfd38ffd9049ffe61195e858b5b110fdffefa16f1440a62078e89b (wtxid=fada93f79fdfd38ffd9049ffe61195e858b5b110fdffefa16f1440a62078e89b) failed but reconsiderable, looking for child in orphanage
2026-10-13T05:45:50.979074Z \[net\] got inv: tx 9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788 have peer=492350
2026-10-13T05:45:50.996410Z \[net\] got inv: tx 9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788 have peer=492349
2026-10-13T05:45:51.016461Z \[net\] got inv: tx 9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788 have peer=492352
2026-10-13T05:45:51.191786Z \[mempoolrej\] 9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788 (wtxid=9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788) from peer=454673 was not accepted: txn-same-nonwitness-data-in-mempool
2026-10-13T05:45:54.662342Z \[net\] got inv: wtx fada93f79fdfd38ffd9049ffe61195e858b5b110fdffefa16f1440a62078e89b have peer=453525
2026-10-13T05:45:55.571249Z \[net\] received getdata for: witness-tx 9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788 peer=439623
... many messages like this one ...
2026-10-13T05:46:01.483448Z \[net\] received getdata for: witness-tx 9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788 peer=446573
# block 971201 (0000000000000000000036fa723572e1e835152288cc97f72e0bafd5cdbb80cd) on our node
2026-10-13T06:19:55.156703Z Saw new header hash=0000000000000000000036fa723572e1e835152288cc97f72e0bafd5cdbb80cd height=971201 peer=320080
2026-10-13T06:19:55.717381Z \[cmpctblock\] Successfully reconstructed block 0000000000000000000036fa723572e1e835152288cc97f72e0bafd5cdbb80cd with 1 txn prefilled, 4395 txn from mempool (incl at least 3 from extra pool) and 1784 txn (203298 bytes) requested
2026-10-13T06:19:56.484269Z UpdateTip: new best=0000000000000000000036fa723572e1e835152288cc97f72e0bafd5cdbb80cd height=971201 version=0x20170000 log2_work=96.388563 tx=1458976279 date='2026-10-13T06:19:32Z' progress=1.000000 cache=526.0MiB(3921176txo)
Final thoughts
Why is p2aburn still active but not harming the metric? Maybe because the fleet is not sending transactions? So they don’t have anything to harm? I suppose fleet operators didn’t realize it yet (nodes off), as we don’t have connections to them? And when they do, will we have the same degradation?
I still need to cross data around what is the reason that each block is not fully on our mempool, requiring getblocktxn call, if data points out to “most blocks are missing a tx from some rune chain” instead of the other options mentioned at delving#1052, it will strengthen this hypothesis.
I still need to really understand P2A, it shouldn’t be that easy to cause this mess in the network, probably I’m missing something out.
Although this post focus on this hypothesis about P2A and sweepers, feel free to comment about other theories. The focus is on why do we see this reconstruction degradation on the network.
On April, I was working on adding some stats based on logs about compact block reconstruction in peer-observer (see 420 and 465), since then, I’ve been looking to the added panels to validate them and I’ve seen some degradation around one of them: Compact block reconstruction without transaction requests per day.
In a simple way, ideally, when a block is mined and someone relay it to us, we’d have all transactions on our mempool. The sender send us a set of short ids of each transaction in that block instead of the full raw version of it, saving some bytes. If we don’t have one of the transactions, we ask the sender for them to be able to reconstruct the full block – a roundtrip that ideally wouldn’t happen. See BIP-152 for more details.
Example of a reconstruction log:
2026-04-06T15:02:09.404125Z [cmpctblock] Successfully reconstructed block 000000...6b6ad5
with 1 txn prefilled,
2714 txn from mempool (incl at least 2 from extra pool)
and 4 txn (886 bytes) requested
I broke some lines to help reading, but it’s just a single line. This log tells us that: 1 transaction came prefilled, coinbase always comes prefilled as probably we wouldn’t have; 2714 were in our mempool and 2 of them were in extrapool, this extra acts like a “pre-discard”, instead of simply erasing it from the mempool, we keep it for some time; and the focus of this post, 4 transactions requested, this causes the roundtrip, making us send a getblocktxn to the sender.
The degradation
The below image shows how much reconstructions requested zero transactions from the sender, based on the previous log. Higher is better.
It shows a clear degradation in this metric from 2026-07-18 to 2026-10-18, from around 35~60% to at most 10% inside the period. This can be also seen in b10c’s nodes as the below image shows, see delving#1052 tables for a longer period.
What does it mean for the network? More roundtrips happening in reconstructions, so more getblocktxn being sent from nodes when (ideally) it shouldn’t happen – among other problems of network.
For a very long time, as a newbie in bitcoin, I had no idea of what could be causing this. But I recently read some posts/comments that opened a great hypothesis for this.
/p2aburn.*/
After reading #193, I took some time investigating those strange agents: /Sat0shi:31.0.0/ and /Satoshi:31.0.0/ with protocol version 70015. I also found another agent behaving similarly /p2aburn.*/, that was also mentioned later in the same post. Later, I found /txbroadcast.*/ which also behaves similarly to those peers.
The moment those nodes first appear seems to correlate with the degradation start and they make sense to impact on this. As mentioned by the author, and also seen on my node, they were sending many unsolicited transactions to our nodes.
At #193 comment, I built a first timeline with each event, but here it is a more updated version:
The bar panels are based on logs and they go from now until 2026-07-08.
The query used for the peer-observer data (line panels) is sum by (useragent) (increase(peerobserver_p2p_version_useragent{useragent=~"/txbroadcast.*|/p2aburn.*|/Sat0shi:31.0.0/"}[1d])). Also, it doesn’t mean that they held X connections on that day.
There’s no way to filter Satoshi:31.0.0 70015 in peer-observer data, but they appear on the panel based on logs.
Timeline:
2026-07-03: /p2aburn-probe:0.1/ first appearance;
2026-07-04: /txbroadcast:0.1/ first appearance;
2026-07-07: a single /p2aburn:0.1/ connection;
2026-07-14: /p2aburn:1.0/ first appearance;
2026-07-18: compact block reconstruction degradation starts (below 10% from 2026-07-23);
2026-07-25: /txbroadcast:0.1/ last appearance;
2026-07-28: /Sat0shi:31.0.0/ first appearance;
2026-09-21: /Satoshi:31.0.0/ (protocol 70015) first appearance;
2026-09-22: /Sat0shi:31.0.0/ last appearance;
2026-10-18: /Satoshi:31.0.0/ (protocol 70015) last appearance;
2026-10-19: after some peaks, /p2aburn:1.0/ falls to about 30~50 connections per day and a very low volume of messages.
At the same time that /p2aburn:1.0/ arrived and started sending a meaningful volume of messages, the metric started declining. And just recently, since many VPS providers rebooted their machines due to CVE-2026-99999 (including mine), see more at #189, this metric bumped to the usual 40~60%. This may have another reasons, but at the moment is my only clue on why they’ve stopped.
Note: from now on, I will call /txbroadcast:0.1/, /Sat0shi:31.0.0/ and /Satoshi:31.0.0/ (protocol 70015) set as the “fleet” – because their behavior are similar, unlike /p2aburn.*/.
Currently, we have zero connections to the fleet and just a few /p2aburn.*/ active, but sending a way lower volume of messages.
Also, see how much tx messages they were sending to my node (based on logs, until 2026-07-08):
For this specific section, most part of it was written by a llm checking my data/logs, it seems to make sense with all the data I’ve seen.
The “fleet” (builds the chains)
It pushes transactions without announcing them. We received 32.9M tx messages from it against only 1.8M inv. A normal peer announces with inv and sends the transaction only when asked. At its peak (Oct 5) it sent ~1.33M transactions a day.
It reconnects constantly. We saw ~31.7k handshakes over the period.
It builds P2A chains carrying Runes:
A root transaction, funded by a wallet input, creates an anchor (290 sats in the chain we followed; other roots use 280, 350 and so on).
Each link spends the previous anchor, pays 10 sats of fee and creates an anchor 10 sats smaller.
When the anchor reaches 240 sats (the dust limit), a refill transaction tops it up again.
A closing transaction pays 679 sats of fee and ends the chain.
Each link mints 1 unit of rune 1:0. Under the mint rule, the runes accumulate on the anchor until the closing transaction.
p2aburn (breaks the chains)
It says the bare minimum. We received only tx (2.96M), pong, version and verack from it. It never sends inv, ping, addr or headers, so it does not announce anything either: it just pushes transactions.
It reconnects a lot. We saw 28,770 handshakes, close to 3k a day at the peak (Oct 17).
It sweeps anchors. Each of its transactions spends an anchor in the middle of a fleet chain and turns the anchor’s whole value into fee. The verified example is sweeper 0b88a628...: 66 vB, 290 sats of fee, and it replaced links 1 to 4 in our mempool. Its average transaction size, ~66 to 80 bytes, fits this. Under the Runes mint rule, a sweep would also burn the runes accumulated on the anchor. That part is inferred: we never decoded a sweeper.
It was already sending transactions on Jul 22, a week before the fleet showed up. We don’t know what it was sweeping then.
It almost stopped after Oct 18. The following days saw ~150 transactions and ~40 connections a day, against 69k transactions on Oct 17. That fits: it ran out of chains to sweep.
The transaction chains
A transaction can spend an output of another transaction that is not confirmed yet. Doing this repeatedly gives a chain: tx1 is in the mempool, tx2 spends tx1’s output, tx3 spends tx2’s, and so on. A miner can include the whole chain in one block, as long as each link comes after its parent.
The “fleet” builds these chains on top of P2A (pay-to-anchor) outputs. A P2A output has a 4-byte script and no key: anyone can spend it without a signature, and the input is the smallest there is (41 vB). Each link in the fleet’s chains:
spends the P2A anchor created by the previous link;
creates a new anchor 10 sats smaller than the one it spends (from 290 down to 240, the dust limit), and a closing tx sweeps the last anchor with a wallet input, paying 679 sats;
carries a Runes OP_RETURN;
is 94 to 107 bytes and pays 10 sats of fee (~0.1 sat/vB).
The chains are up to 25 links long. Since there is no key, the fleet can build and broadcast whole chains very fast. The flip side is that the same property lets anyone spend an anchor in the middle of a chain.
Those 25 txs clusters are very common to be in mempool, take a look at the below metric taken out of Cluster Mempool Observer histogram. Btw it’s a personal project to track a history of every movement of the mempool and its clusters (still experimental). Here you can look at many examples of them individually, and here you can see them in mempool space.
Also those “Rune mint chains” possibility is mentioned at delving#1052.
How a mid-chain replacement could degrade compact block reconstruction
I personally didn’t know much about P2A, tried to learn a bit about it. Feel free to correct me if I say anything wrong.
This is my main hypothesis right now, since a single transaction is all that’s need to trigger a getblocktxn in reconstruction, I think this can be great part of the reason why we see this degradation.
Anyone who gets a conflicting spend of one link into the mempool can cut a chain of unconfirmed transactions. For example:
A chain of 10 transactions, tx1 to tx10, each spending an output of the previous one.
Someone broadcasts tx5’, which spends the same input as tx5 and pays a higher fee.
My node correctly accepts tx5’ under the RBF rules and evicts tx5 along with its descendants, tx6 to tx10. If tx5’ arrives first, the node rejects tx5 instead, and tx6 to tx10 never get in because their inputs are missing.
A miner that has the original chain and never takes tx5’ mines all 10.
When the block arrives, my node is missing tx5 to tx10. It cannot rebuild the block from the compact block alone and has to fetch them with getblocktxn. Bitcoin Core keeps recently replaced transactions in extrapool for this case, but at high enough volume they no longer fit.
My node did nothing wrong at any step. Its mempool holds a valid history that differs from the one the miner chose.
Cost
With plain RBF, the replacement must pay more in absolute fees than everything it evicts. It costs nothing only when it never confirms, which is what happens in the example: the block containing the original chain invalidates it. If a miner picks up tx5’ instead, the sender pays.
P2A anchors remove most of that cost. Because anyone can spend an anchor, the sweeper’s fee comes almost entirely from the anchor’s own value. In what I saw, a sweeper spends an anchor and turns its whole value into fee (290 sats for the root anchor), so the sender adds nothing of their own.
In this case, my node already have the rest of the chain, so it rejected the sweeper, but later a miner mined the sweeper.
fada93...89b log history
# sweeper fada93f79fdfd38ffd9049ffe61195e858b5b110fdffefa16f1440a62078e89b and its parent 9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788
2026-10-13T05:45:50.736096Z \[validation\] Enqueuing TransactionAddedToMempool: txid=9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788 wtxid=265a8c7dad0c3e0fb0329777c279aab78b031b149333357ec3fade3ec42d7c4f
2026-10-13T05:45:50.736226Z \[mempool\] AcceptToMemoryPool: peer=492350: accepted 9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788 (wtxid=265a8c7dad0c3e0fb0329777c279aab78b031b149333357ec3fade3ec42d7c4f) (poolsz 80331 txn, 219945 kB)
2026-10-13T05:45:50.736435Z \[validation\] TransactionAddedToMempool: txid=9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788 wtxid=265a8c7dad0c3e0fb0329777c279aab78b031b149333357ec3fade3ec42d7c4f
2026-10-13T05:45:50.882843Z \[mempoolrej\] fada93f79fdfd38ffd9049ffe61195e858b5b110fdffefa16f1440a62078e89b (wtxid=fada93f79fdfd38ffd9049ffe61195e858b5b110fdffefa16f1440a62078e89b) from peer=491503 was not accepted: insufficient fee, rejecting replacement fada93f79fdfd38ffd9049ffe61195e858b5b110fdffefa16f1440a62078e89b, not enough additional fees to relay; 0.00 < 0.00000007
2026-10-13T05:45:50.882883Z \[txpackages\] tx fada93f79fdfd38ffd9049ffe61195e858b5b110fdffefa16f1440a62078e89b (wtxid=fada93f79fdfd38ffd9049ffe61195e858b5b110fdffefa16f1440a62078e89b) failed but reconsiderable, looking for child in orphanage
2026-10-13T05:45:50.979074Z \[net\] got inv: tx 9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788 have peer=492350
2026-10-13T05:45:50.996410Z \[net\] got inv: tx 9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788 have peer=492349
2026-10-13T05:45:51.016461Z \[net\] got inv: tx 9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788 have peer=492352
2026-10-13T05:45:51.191786Z \[mempoolrej\] 9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788 (wtxid=9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788) from peer=454673 was not accepted: txn-same-nonwitness-data-in-mempool
2026-10-13T05:45:54.662342Z \[net\] got inv: wtx fada93f79fdfd38ffd9049ffe61195e858b5b110fdffefa16f1440a62078e89b have peer=453525
2026-10-13T05:45:55.571249Z \[net\] received getdata for: witness-tx 9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788 peer=439623
... many messages like this one ...
2026-10-13T05:46:01.483448Z \[net\] received getdata for: witness-tx 9d887fdb2cd62c6af31801f4f9dc2dece40b0c69255c8a46125275368bf8b788 peer=446573
# block 971201 (0000000000000000000036fa723572e1e835152288cc97f72e0bafd5cdbb80cd) on our node
2026-10-13T06:19:55.156703Z Saw new header hash=0000000000000000000036fa723572e1e835152288cc97f72e0bafd5cdbb80cd height=971201 peer=320080
2026-10-13T06:19:55.717381Z \[cmpctblock\] Successfully reconstructed block 0000000000000000000036fa723572e1e835152288cc97f72e0bafd5cdbb80cd with 1 txn prefilled, 4395 txn from mempool (incl at least 3 from extra pool) and 1784 txn (203298 bytes) requested
2026-10-13T06:19:56.484269Z UpdateTip: new best=0000000000000000000036fa723572e1e835152288cc97f72e0bafd5cdbb80cd height=971201 version=0x20170000 log2_work=96.388563 tx=1458976279 date='2026-10-13T06:19:32Z' progress=1.000000 cache=526.0MiB(3921176txo)
Final thoughts
Why is p2aburn still active but not harming the metric? Maybe because the fleet is not sending transactions? So they don’t have anything to harm? I suppose fleet operators didn’t realize it yet (nodes off), as we don’t have connections to them? And when they do, will we have the same degradation?
I still need to cross data around what is the reason that each block is not fully on our mempool, requiring getblocktxn call, if data points out to “most blocks are missing a tx from some rune chain” instead of the other options mentioned at delving#1052, it will strengthen this hypothesis.
I still need to really understand P2A, it shouldn’t be that easy to cause this mess in the network, probably I’m missing something out.
Although this post focus on this hypothesis about P2A and sweepers, feel free to comment about other theories. The focus is on why do we see this reconstruction degradation on the network.
Thanks for putting this together. I don’t log cmpctblock, but I have a side measurement that moves at the same time: for each new block, the gap between the first job from a local stratum server fed by my own Core and the fastest of three public pools.
Same node, no restart, the same manual peers until Oct 21. Median gap:
Oct 7 – Oct 18 13:28 UTC (last fleet session here): 249 ms over 1,741 blocks
Oct 18 13:28 – Oct 22: 115 ms over 600 blocks I had to restart my node on Oct 22.
My node’s own block detection minus the fastest pool drops the same way (209 → 98 ms), so it’s not just template building. And since my node wasn’t restarted around Oct 18, the change here isn’t from a reboot.
My guess is your effect: my mempool was missing transactions from new blocks, so Core had to fetch them first. One extra round trip fits the size of the step. It’s one node and only a correlation, and my data starts mid-September.
Follow-up: I checked every block from Oct 7 to Oct 22 for fleet txs. Blocks without any sped up just the same. SecPool and Luxor never included a fleet tx or a sweep, yet on my node:
SecPool: 356 → 114 ms
Luxor: 330 → 98 ms
So here it doesn’t look like the chain txs inside the block were the main cause. Something else in the mempool, maybe? Small samples after Oct 18, and no cmpctblock logs, so I can’t say more. Sorry for the hasty guess earlier.
I had some peer-observer archives from Aug 12 and Aug 18–19, so I went looking for the fleet and decoded the txs it pushed to us. They look exactly like the P2A chains described above!
The fleet showed up as /Sat0shi:31.0.0/, always inbound. It sent around 3.4k tx and only ~130 inv, and it never requested anything back. Every tx carries a runestone. Almost all of them are 25-long chains:
a root tx with a ~474 sat P2A output
24 links, each spending the previous anchor and paying 10–11 sats of fee (~0.1 sat/vB)
a tail tx paying ~13 sat/vB, which pulls the whole chain in with CPFP
On Aug 12 we also had mempool events, and I could see the sweeps happening. They’re 66 vB txs that pay exactly the anchor’s 474 sats as fee, and each one evicted up to 17 links. On the same day, a good chunk of the fleet’s txs were mined, others were replaced, and a few hundred were rejected for missing inputs.
p2aburn did connect to this node, but it never sent a tx. It only did handshakes, so the sweeps reached us through other peers.
I haven’t cross-checked any of this against our cmpctblock getblocktxn yet
Will post it once I have it.
I cross-checked against our cmpctblock / getblocktxn
Only 5 of 162 compact blocks were reconstructed without a round trip.
About 96% of the txs we had to request were fleet chain links, and another 2–4% were sweeps. In 53 blocks, nothing else was missing. The worst block, 963060, needed 4,757 of its 7,049 txs, and 4,715 of those were fleet
Without the fleet and sweep misses, 36% of these blocks would have reconstructed with no round trip at all (vs 3% actually), and 54% would have been missing at most one other tx.
Most of the missing links had already reached us before the block, relayed by normal peers. We had rejected them with bad-txns-inputs-missingorspent (~87% on Aug 12) because their anchor input was gone or already spent in our mempool. The mined sweeps had been rejected for insufficient fee.
The three worst blocks look different: 963059 (Foundry), 963060 (Binance, 14 s later) and 963130 (AntPool). Each one came during a big fleet burst.
Incoming txs jumped ~15x right before 963130. During the burst, every tx (not just fleet ones) took ~10–30 s to show up on our node instead of under a second, so the pools mined the burst before we had it. That might also explain what @benunskilled saw: his node got faster at picking up new blocks after Oct 18, even for blocks with no fleet txs at all (SecPool, Luxor)
If anyone has data from another node around Aug 18 14:48 UTC or Aug 19 04:32 UTC, comparing would be great
I’m happy to check anything else in these archives too, any questions? I hope so because this isnt really clear for me yet but idk what else to search for
Good catch, I didn’t know there were pools that didn’t mine them.
I have a guess about it, no easy way to prove it, but I think as node’s extrapools were being flooded by this sweeper problem, other “innocent” clusters (of txs) were being harmed and not properly mounted in the mempool (orphan eviction).
I was seeing a similar estimative around this, and although there were another types of txs missing, great part of it were fleet chain links. I imagine that miners have a really “boosted” node, so their extrapool is quite far bigger that the default 100 size, and it ends helping them to build the best clusters of txs – which is usually the fleet one, not the sweeper.
For reasons of reproducibility of this post, I organized a repository that allows you to go through your node’s logs and see similar graphs. It requires some debug flags turned on: net (main one), cmpctblock, mempoolrej. Its readme also contains which logs are being used, if you want to do an independent check. I changed to not use peer-observer data, as not everyone has it on their nodes, although readme still mentions related promql.
Besides that, I’m working on gathering the reasons of each requested tx and also building a warnet simulation of each actor from this post (fleet, sweeper…). I’ll say upfront that, the real problem is when the fleet AND sweeper (p2aburn) are announcing txs. The fleet building P2A chains and the sweeper cutting them, in volume, kills the purpose of the extrapool (and maybe also TxOrphanage?).
Extra: P2A had a great increase in “Input Types by Count” since 2026-07-01 until 2026-10-18, which fits our observations. See Input Types by Count, in 1d moving average you can see the start and end of it.
As a last contribution to this post and to not throw it away, I did a warnet experiment to try to prove those affirmations. It’s included in this repository if you want to check in details. But here it is the most important informations about the simulation:
36 nodes (core v31): 3 miners, 30 innocents and the actors (mint, fleet, sweeper);
Mint: create common rune mints, without P2A, chains between 20 to 24 txs; sends 4.7 tx/s;
Fleet: create P2A chains, on each chain we have a root tx, links (P2A txs), tail (CPFP), refill (increase feerate); sends 2.1 tx/s;
Sweeper: each 1 second it queries the mempool looking for P2A chains, choses a random P2A tx from each found chain and send a sweep tx spending everything as fee.
Each node receives 1 or 2 nodes via addnode initially, then they start to connect as usual;
blockmaxweight 400000 (10% of the default value);
Extrapool cap blockreconstructionextratxn 20 (default is 100);
Each block is mined every 1 minute;
Each miner creates its template every 15s and just after every mined block;
Phases (~2h):
5 min warmup;
7 phases of 17 min: control → all → no-sweeper → all → no-fleet → all → no-mint;
The next images show similar metrics as reported in the first comment, but for the simulation. We can see that clearly, if the fleet and the sweeper are active, the metric is degraded.
It’s interesting to see that even the mint node not participanting directly on the degradation, it did some snow balling effect, with it disabled the metric raised from ~73% to 83%. As I commented last week, I think that as other transactions that also needs the extrapool to be mounted properly (as the chains sent by mint node), this increases the harm of it.
I ran some tests with variations of blockreconstructionextratxn (extrapool cap), and as expected, it had a great correlation on how many reconstructions didn’t need a getblocktxn.
Additionally, I asked for a llm to query for possible related projects to this case based on the data I already had. So summarizing its findings: it seems that a project called alkanes-rs did a fork in its way of working in height 972000, which matches the last P2A chains being relayed/mined – and if that’s really the case, invalidates my initial hypothesis that it stopped due to vps reboots related to CVE-2026-99999.
How the llm identified who it was?
Example tx: 13b821bc...092d2a (the “Confirmed chain” above), block 971942.
The proof is in three parts of the OP_RETURN, each defined in the alkanes-rs code. Only the first is visible in the raw hex; the other two appear after decoding the tag’s value:
The most direct link is DIESEL’s own mint counter. At precompile_diesel.rs:317 it skips protostones with protocol_tag != 1, and at lines 336-338 it counts those calling 2:0 with opcode 77. The tx carries exactly these values, so the project’s code counts it as a DIESEL mint.
The project identifier is the 01, not the ff7f: tag 16383 only says there is a protostone, and the 1 says it belongs to Alkanes.
I didn’t go too far on this as it’s not of my interest understand those projects, and we already have a great understanding of what’s the problem in the network.