An overview of recent non-standard Bitcoin transactions
Monday, January 29, 2024This blog post provides an overview of non-standard transactions that mining pools included in the last 117000 Bitcoin blocks.
Usually, before a Bitcoin transaction is included in the blockchain, it is relayed between nodes on the Bitcoin P2P network and cached in their mempools. To mitigate some transaction relay Denial-of-Service attacks, the Bitcoin Core node limits what transactions can be relayed. Transactions deemed as “standard” are relayed, while “non-standard” transactions are not relayed. In Bitcoin Core, these rules are known as the policy rules. Mining pools can receive non-standard transactions out-of-band or loosen the relay rules to accept them over the P2P network. Non-standard transactions can be, and frequently are, mined.
This post provides an overview of recent non-standard transactions included by mining pools. Frequent non-standard transactions might show policy rules that need to be adapted or changed, while ensuring no Denial-of-Service attacks are made possible. Having an overview of which non-standard transactions are mined and who mines them can serve as basis for future policy design. Additionally, vulnerabilities in Bitcoin software came to light, which require mining non-standard transactions to be exploited. Some of these vulnerabilities have been exploited, while others have been responsibly disclosed. Some mining pools try to extract more value from blocks than just the block reward by including non-standard transaction. This is generally known as Miner Extractable Value (MEV). A large mining pool might be able to extract more value by investing heavily into their transaction selection software to out-compete smaller mining pools. This causes further mining pool centralization.
Methodology
To detect non-standard transactions, two nodes are used. A data-node and a
test-node. The data-node has access to the full blocks that should be checked1.
The test-node is synced to a height just below the test-start-height. It can be a
pruned node. Now, beginning from the test-start-height, blocks are requested from the
data-node. For each transaction in a block, excluding the coinbase transaction, we test
if the transaction is accepted to the test-node’s mempool using the testmempoolaccept
RPC call. If the transaction is rejected from the test-node’s mempool, then the
transaction is non-standard. The rejection reason is recorded. If the transaction is
accepted, it is submitted to the test-node with the sendrawtransaction
RPC call. This
makes sure child transactions aren’t rejected due to parents from the same block not being available.
Once all transactions have been tested, the block is submitted to the test-node
with the submitblock
RPC call. This clears the mempool. The next block is tested
until the chain tip is reached. This methodology is implemented in the quick and dirty tool
github.com/0xB10C/find-non-standard-tx.
While this methodology reliably detects non-standard transactions, there are a few limitations. For example, there is only one reject reason returned for a transaction even if the transaction would be rejected for multiple reasons. Furthermore, descendants of rejected transactions can’t be added to the mempool as their inputs are missing. These have to be analyzed manually. The ordering in the block might not represent the order in which transactions entered the mempool. Usually, this isn’t a problem. However, for the CPFP carve-out rule to be applicable, the 25th descendant has to be added last. This results in one transaction being rejected with an “too-long-mempool-chain” when the CPFP carve-out rule was used (but also allows detecting and measuring the use of CPFP carve-out).
Non-standard transactions by rejection reason
Here, a start height of 710575 (2021-11-20) and an end height of 827622 (2024-01-27) was used, which results in about 117k blocks checked for non-standard transactions. The start height was chosen to be shorty after Taproot activation. A Bitcoin Core v26.0 node was used as test-node. The following overview does not cover all 20k non-standard transaction detected. Rather, it picks out a few interesting examples and tries to highlight the reasoning behind these non-standard transactions, where possible.
“bad-txns-nonstandard-inputs”
In January 2023, between block 771609 and block 773957, MaraPool included 16
non-standard transactions in their blocks. These were all rejected with the
reason: bad-txns-nonstandard-inputs
. In this case, the redeemScript
s in the
inputs have more sigops than allowed. This is related to Bitcoin Core PR #26348
by Sergio Demian Lerner, where he describes that the RSK sidechain migrated
to a non-standard P2SH redeemscript with now more than 3000 BTC stuck on there.
MaraPool helped RSK by mining the non-standard transactions. Sergio noted, that
their tests on testnet passed. At the time, non-standard transactions were allowed
by default on testnet. This was later changed in the Bitcoin Core PR #28354.
“tx-size”
As a protection against excessive resource usage, Bitcoin Core does not relay and rejects transactions
larger than 100 kvB (400 kWU; MAX_STANDARD_TX_WEIGHT
). These are rejected with the reason “tx-size”.
The Luxor pool mined the 985 kvB (3.94 MWU), zero-fee transaction 0301e0480b in block 774628 (2023-02-01). This transaction inscribes an 1803 × 1803 pixel JPEG showing a taproot wizard with a size of 3.9 MB and fills nearly the entire block.
Block 776884, mined by Terra Pool, includes the 850 kvB transaction b5a7e05f28 , paying nearly 0.5 BTC in fees. The transaction inscribes a 1-minute MP4 music video showing a frog holding a drink. In block 777945, the 975 kvB transaction 79b91e594c pays a fee of nearly 0.75 BTC to inscribe a 4000×5999 pixel WEBP image. The 992 kvB transaction 4af9047d8b , mined in block 786501, pays nearly 0.5 BTC in fees to inscribe a 2040×2653 pixel JPEG image of a Bitcoin Magazine cover with the face of Julian Assange.
F2Pool frequently includes larger-than-standard transaction in their blocks. These are mainly zero-fee mining pool payout transactions with one input and more than 3000 outputs. Examples are b460f75888 , 56c5b34eac , and 8239fbb0da .
There are two F2Pool transactions that are not pool payouts and stand out. The zero-fee transaction
7884712aae
has 800 inputs and 800 outputs, with a size just above 152 kvB. All inputs and
outputs are 546 sat. This transaction moves F2Pool’s “uncommon sats”2
to a different address. Transaction
73be398c4b
has a size of 125 kvB and pays the complete input amount of 0.03682719 BTC ($750 USD
at the time) as fees. The only output is an OP_RETURN output with the message
“you'll run cln. and you'll be happy.
”. This transaction exploited a consensus
bug in btcd causing, for example, LND, to stop processing new blocks. This transaction
was constructed by brqgoo.
“non-mandatory-script-verify-flag”
The transaction
00c1af8f7d
is non-standard with the reason “non-mandatory-script-verify-flag (OP_SUCCESSx
reserved for soft-fork upgrades)”. This transaction has a size of 104 vB and pays a
fee of 5000 sat. It was also constructed by brqgoo and, similar to the previous
transaction, also includes an OP_SUCCESS
. It was, however, mined before the transaction
that exploited the consensus bug in LND and might have been a test transaction. The
only output is an OP_RETURN with a 32 byte value, which could be a hash
commitment to the later exploited vulnerability.
possible hash commitment: 5d86c2f206e5d9eb8c797035039ffac92ed94f794f9dab764be0ba40491dec47
“scriptpubkey” & “multi-op-return”
In block 826775, F2Pool mined transaction c3dd9ae8b5 , which included a 100 byte OP_RETURN message. Similarly, in block 826796, F2Pool mined transaction ee8bbff798 with a 686 byte OP_RETURN message, in block 827419 17ec5d7066 and 2c869583a8 with 111 byte and 400 byte OP_RETURN messages. OP_RETURN is, by default, limited to 80 bytes of data. These transactions were rejected with the reason “scriptpubkey”. F2Pool also mined the transactions cb22f12d77 and 6f660e9f1b , which have five and two OP_RETURN outputs. As, by default, only one OP_RETURN output is allowed, these are non-standard with the reason “multi-op-return”.
While these transactions are non-standard when using Bitcoin Core, they are standard when using Peter Todd’s “Libre Relay” patch. In particular, these changes allow large OP_RETURN messages and multi-OP_RETURN transactions. F2Pool might be running the “Libre Relay” patches.
While writing this blog post, more non-standard “scriptpubkey” transactions were mined by F2Pool. For example, the 3.22 kvB transaction 8c9fe58186 encodes a PNG image and 33a271fd77 a GIF. For more transactions, see this tweet thread.
“min relay fee not met”
By default, Bitcoin Core has a minimum relay fee of 1 sat/vByte. Transactions
below this feerate are rejected and not relayed to other nodes.
These are often sent to the mining pool out-of-band. Some mining pools
might opt to mine their own zero-fee transactions. By creating zero-fee
transactions and using, for example, the prioritisetransaction
RPC to assign
a virtual fee, they avoid their transaction from being relayed but still can
get it accepted into their mempool. If they construct a transaction that pays
a fee, they risk that it’s relayed to another pool and pays a competing mining
pool. Additionally, depending on the mining pool’s payout and fee structure,
including their own zero-fee transactions might shift the transaction fee costs
to their miners. As the pool’s zero-fee transaction takes up block space, it
reduces the transaction fees earned by their miners. The miners might not be aware
of being exploited by the pool.
ECMD Pool mined b1360f73a7 paying 7400 sat at 14 kvB resulting in a 0.52 sat/vB feerate. This transaction consolidates 96 inputs to the sending address and sends 43k USDT (Omnilayer) to Huobi3 in a nearly-dust output. The consolidated inputs don’t seem to stem from EMCD Pool themself. It’s unclear why the transaction did not pay more than the minimum relay fee of 1 sat/vByte. The output of the transaction was spent in the same block with a feerate of 89.1 sat/vB4. While this results in an effective feerate of over 2 sat/vB through CPFP, the first transaction would not have been relayed.
Transaction 9ffad0add0 , paying a feerate of 0.43 sat/vB with a fee of 7701 sat and a size of 17 kvB, was mined by SBICrypto. It consolidates 100 inputs into a single output. The addresses belong to the freebitco.in entity3. Why freebitco.in constructed a transaction paying below the minimum relay feerate is not known.
The transaction
4da9b2ab35
was mined by an unidentified pool5. It does not pay fees
and script-path-spends a 2-of-2 multisig P2TR output. The parent transaction
creates an OP_RETURN output with a valid but unused bech32 address
bc1qypz2ynlgy3dmpqxxvap2s30wjfqcp24tk46p83
. It’s unknown why the
transaction does not pay fees.
The mining pool Terra Pool mined the zero-fee transaction 1a6466600e in block 811775 creating a 10k sat output. The output was directly consumed by the next, also a zero-fee, transaction f9aa65bb55 in the same block. It inscribes a “Clean Bitcoin Certificate”. In a block mined by a “Clean Incentive” pool, the transaction d2a769546e creates an additional 10k sat output. This output, and the previously inscribed certificate, are then consumed by another zero-fee transaction, ed8819d17d , which inscribes an accompanying JSON object with more information about the certificate. This is later moved in yet another zero-fee transaction 7cc18418b8 , where a collection of inscriptions is inscribed.
The same pool also mined the zero-fee transaction
699e9a9632
,
which has one input and one output. It spends a 1-of-2 P2SH output created
in the same block. The 1-of-2 multisig is composed of two public keys with well-known
private keys. The private keys are 1
and 2
6. The transaction creating
the multisig output has a feerate of 3.9 sat/vB and is the first transaction in
the block after the coinbase. As the remaining transactions in the block pay a
significantly higher feerate, this is an indication the transaction was manually
prioritized by the pool. The pool might run a tool that checking for UTXOs spendable
with well-known private keys, and tries to spend and mine them before someone else
does 7.
MaraPool mined the zero-fee transaction
0026faeccb
,
which script-path-spends a single P2TR output from a depth-2 merkle tree, revealing
a 1-of-1 multisig. The parent transaction has an OP_RETURN output with the data
cc1qjdexdhgqu95zfkvw20vfn3uh9r6s563y86qpsd
. It’s unclear why MaraPool mined
this zero-fee transaction.
F2Pool frequently mines zero-fee transactions. These are mainly consolidations
of their coinbase outputs and pool payout transactions8. An
example for a coinbase consolidation is transaction
11887bfc72
.
It consolidates 21 inputs from 1KFHE7w8BhaENAswwryaoccDb6qcT6DbYY
, the well-known
F2Pool coinbase output address, into two outputs paying no fees.
However, it seems F2Pool is also using zero-fee transactions for payments to Huobi (44335aef14) and Binance (a5c062118a). While these are small, one-input two-output transaction and don’t take up much block space, they reduce the fees earned in the block and the payout distributed to F2Pool’s miners.
In block 730459, F2Pool mined the zero-fee, one-input one-output transaction
26a9e3872f
,
which moved 3900 BTC from 1J1F3U7gHrCjsEsRimDJ3oYBiV24wA8FuV
to the same address. While
this seems pointless at first, one explain could be that there existed an
alternative, (pre-) signed transaction spending this UTXO. To invalidate this transaction,
the UTXO was spent. The transactions
03e43f5e28
and
68e129eb0a
are similar occurrences.
F2Pool also transferred it’s “uncommon sats”2 to another address in the38 kvB transaction 9f62795a47 . This transaction has 200 inputs and 200 outputs worth 546 sat each. F2Pool sells “uncommon sats”2, starting at 450 USD for a single 546 sat UTXO7.
“dust”
Bitcoin Core treats low value outputs as non-standard or “dust”, when the output value is lower than the cost of creating and spending it. Dust UTXOs aren’t economical to spend and pollutes the UTXO set. F2Pool is the mining pool that frequently mines transactions, creating “dust” outputs.
In the Stacks 2.0 mining protocol, stacks-miners try to get their commit transaction into the next block by paying a high fee. In their commit transaction, they include, as a proof-of-transfer, two outputs to two other stack miners. The higher the (bitcoin) amount of these outputs, compared to the other stack-miners competing for the same block, the higher the probability to mine the Stacks block and be rewarded. There is no minimal proof-of-transfer amount besides the Bitcoin dust limit. F2Pool is using their position as a mining pool to their advantage7. They filter all stacks block commits broadcast by other stacks-miners. This allows them to include only their own commit transaction in their block. In this zero-fee transaction, they pay dust outputs to two other stack-miners. This allows them to have a 100% probability of being rewarded while only having to spend a few sats.
F2Pool creates other dust outputs too. In the zero-fee transaction 638d8cf6da , F2Pool splits their “uncommon sats”2 from some of their coinbase payout outputs into separate UTXOs. While these separate UTXOs all have a value of 546 sat, there is one UTXO created with a value of 330 sat, which makes it a dust output. On the output, according to the ordinal theory, a portrait of a frog in a suit is inscribed. This inscription was inscribed about 40k blocks before F2Pool split these out. The inscription somehow made its way to one of F2Pool’s addresses.
F2Pool also mined the one-input two-output transaction d82e322d9d , which creates a 250 sat dust output. It’s unclear why this transaction was included by F2Pool. The transaction 38086f6079 creates two dust outputs and was sent to F2Pool out-of-band. The story behind this transaction can be found on Twitter.
F2Pool mined the one-input and one-output transaction
2814d0a3c9
,
paying a fee of 10k sat. The output has a value of zero, which is below the dust limit.
This zero-value output is spent in transaction
c1e0db6368
,
which inscribes a text inscription you will use soma and you will like it
and creates another zero-output.
An inscription on a zero-value output broke the ordinals index. These transactions
were created by supertestnet, who later released his code in a tool called breaker-of-jpegs.
There are plenty of other cases where F2Pool included transactions that create outputs below the dust limit. This could indicate that they use a lower dust limit than what’s set by default.
“too-long-mempool-chain”
By default, Bitcoin Core limits the number of in-mempool descendants a transaction can have to less than 25. An exception is the CPFP carve out rule, which allows a single, small child of the top most ancestor transaction. When these limits are exceeded, transactions are rejected with the “too-long-mempool-chain” reason. These transactions are usually standard on their own but aren’t accepted into the mempool at the same time.
In block 788839, ViaBTC included multiple ancestry sets with more than 200 transactions in total. These would have been rejected from a default mempool. These sets include the transactions 6cd3e204ae and 174f1695d5 . Both ancestry sets are related to minting BRC-20 tokens.
In block 789149, AntPool mined an ancestor transaction A d4431ed437 with 28 descendants as part of an BRC-20 token mint. With default Bitcoin Core rules, only 24 children would have been allowed.
In block 802625, F2Pool mined an ancestor A
1a4fa7cadc
with two descendants. The children are rejected from a default mempool with the reason “too-long-mempool-chain”.
Here, the ancestry set is clearly under the limit of 25 transactions. However, the ancestor
A has a size of 52 kvB, child 1 a size of 60 kvB, and 2 a size of70 kvB. The default
Bitcoin Core configuration only allows an ancestry set to have a maximum size of 101 kvB
(DEFAULT_ANCESTOR_SIZE_LIMIT_KVB
). Transaction A and child 1 together already exceed
this limit. These transactions seem related to the KuCoin exchange3.
As mentioned in the methodology limitations, occurrences of CPFP carve out are incorrectly rejected with “too-long-mempool-chain”. The ordering in the block is different from the valid mempool submission order. An example is 0b9900440d mined by Binance Pool. This ancestor transaction A has a child transaction 1. Transaction 1 has transaction 2 through 24 as children. This is the maximum number of allowed children. Transaction 25 is a direct child of the ancestor A and has a size smaller than 1000 vB, which makes it a valid CPFP carve out. Future work could closer analyze how the CPFP carve out rule is being used on the network.
Conclusion
Non-standard transactions are frequently included by mining pools. While some pools occasionally help community members by, for example, mining UTXOs stuck on non-standard scripts, other pools use their position as pool to extract more value from blocks. The F2Pool mining pool is clearly the pool having the least strict standardness rules and, from time to time, they accept to mine transactions that exploit vulnerabilities in Bitcoin related software. The recent non-standard transactions don’t immediately show standardness rules that need to be changed.
An alternative to a data node could be a block explorer API serving the full blocks. ↩︎
And it tries to double spent the 43k USDT. https://omniexplorer.info/search/05abfed93a56683ac909e1e0142c0f90f1180e04ba42b18841abcc7c820809d0 ↩︎
The private key
1
corresponds to the address1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH
and the private key2
to the address1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP
. The particular P2SH address used here is38fEX6RbBBMmpu3nbbuULku1xyrrzqqqnE
. This is a 1-of-2 and a 1-or-2 multisig! ↩︎These are usually too large and listed under the
tx-size
section. ↩︎