Bitcoin Forum
May 11, 2024, 12:04:34 AM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Shortest possible raw transaction (below 85 bytes possible)?  (Read 231 times)
BTCW (OP)
Copper Member
Full Member
***
Offline Offline

Activity: 193
Merit: 235

Click "+Merit" top-right corner


View Profile
August 30, 2020, 05:01:35 PM
Merited by Mitchell (3), o_e_l_e_o (2), Husna QA (1), NotATether (1)
 #1

I have experimented with creating the shortest possible raw transaction, which has been successfully broadcast and mined.

A very quick Google search (my due diligence is admittedly so-so) reveals that someone boasts about sending a 129-byte transaction.

I have sent an 85-byte transaction! Txid: fbff3bdec5b34bff4e3bd9066fd53262b014abe0227898ce9bcc8552f31f7394

Is it possible to beat this, i.e. do even shorter than 85 bytes?

My strategy:

-- Spend from an any-one-can-spend address with a 4-byte sigscript (I have failed to go shorter than this, can you?)
-- Send to a native segwit address, the shortest of the predefined standard formats

Here is my transaction...

Code:
01000000012f107ec7a860784725acc93d2362a0dc9b2560eafe5ff3f0b1faef5e0831517b0100000003510161ffffffff0186959800000000001600141ee44a2f2c8d366945ff02676bd608f70a559ea700000000

... and let's break it down (and look for any potential room for improvement):

01000000 - version number (always 4 bytes)
01 - number of inputs (always 1 byte)
2f107ec7a860784725acc93d2362a0dc9b2560eafe5ff3f0b1faef5e0831517b - txid in little endian format (always 32 bytes)
01000000 - vout little endian (always 4 bytes)
03510161 - sigscript including length byte padding (1+3=4 bytes)
ffffffff (sequence number - always 4 bytes)
01 - number of outputs (1 byte)
8695980000000000 - amount (little endian, always 8 bytes)
1600141ee44a2f2c8d366945ff02676bd608f70a559ea7 -- (a native segwit address, 1+22=23 bytes [shortest possible standard address])
00000000 - locktime (block 0, always 4 bytes)

4 + 1 + 32 + 4 + 4 + 4 + 1 + 8 + 23 + 4 = 85 bytes

Seems to check out.

OK, can we go shorter? My reasoning - I'd love your comments:

-- Most of the values have hardcoded lengths, you can for example never reference a txid that isn't exactly 32 bytes

-- I want the transaction to be accepted on the mainnet, which excludes sending to pure scripts (P2S), as these are no longer accepted by Bitcoin Core nodes, due to IsStandard() and IsStandardtx() checks, so we are limited to the predefined address formats of which native segwit is the shortest, byte-wise (and there is no witness data here since we use a stupid any-one-can-spend address)

-- All my attempts to assemble shorter sigscritps have failed. A sigscript must contain an unlocking script that is "push only", so OP_1 (51) it is for the unlocking script, and it must be followed by the locking script, which cannot be empty (I think?!), and the whole shebang must be prefixed with a length byte; I haven't been able to get anything below 4 bytes in total to work

-- You could cheat and spend to OP_RETURN 01 only, which is considered a standard address (whether you like it or not); such transactions, however, always lead to provably unspendable outputs, so add that to my list of requirements: the transaction should not trap coins in unspendable outputs

Is my 85-bytes transaction some sort of record? If so, cool, I guess.

Can we go shorter than 85 bytes? Shoot! Thanks.


SendBTC.me <<< amazing imitative
The forum strives to allow free discussion of any ideas. All policies are built around this principle. This doesn't mean you can post garbage, though: posts should actually contain ideas, and these ideas should be argued reasonably.
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
1715385874
Hero Member
*
Offline Offline

Posts: 1715385874

View Profile Personal Message (Offline)

Ignore
1715385874
Reply with quote  #2

1715385874
Report to moderator
achow101
Moderator
Legendary
*
expert
Offline Offline

Activity: 3388
Merit: 6635


Just writing some code


View Profile WWW
August 30, 2020, 06:46:32 PM
Merited by o_e_l_e_o (2), BTCW (2), Mitchell (1), ABCbits (1), DougM (1)
 #2

The smallest transaction that can be relayed is 82 bytes. There is a hard minimum at 82 bytes as that is the non-witness size of a 1 in,  1 out P2WPKH transaction. The limit is there to protect against CVE-2017-12842.

You can shave off 1 byte by using a redeemScript of just OP_TRUE. Then you won't need to push anything else to the stack in the scriptSig.

If you are willing to make an output that only miners can spend, but can still be relayed, then you can create a witness output with an unknown witness version. Currently only segwit v0 is defined, but segwit currently allows up to version 16. Besides v0, only v1 has been proposed - this is taproot. You can use the other witness versions and transactions containing those outputs will still be relayed. The caveat is that those outputs cannot be spent because spending them is non-standard. Only miners can spend them since they aren't consensus invalid. And if you wait too long to spend them, they will become unspendable when that witness version is defined.

So you can replace your P2WPKH output with an unknown witness version and just pad it up to the 82 byte minimum. Furthermore, such an output will also have a bech32 address, and in theory, any wallet that supports segwit can send to that address.



In case you are wondering, I did also try a couple of other weird things to get small transactions. Unfortunately they don't work.

I was able to make a 64 byte transaction using the unknown witness version trick, but because I was trying to spend an output with an unknown witness version, this was non-standard and wasn't accepted by my node.

It is possible to make a 0-of-0 multisig, and Bitcoin does allow bare multisig scriptPubKeys. However the standardness check on multisigs requires at least a 1-of-1, so this didn't work either.

gmaxwell
Moderator
Legendary
*
expert
Offline Offline

Activity: 4172
Merit: 8419



View Profile WWW
August 30, 2020, 09:57:13 PM
 #3

Please don't. Using transactions below the standard size limit will interfere with fixing a security vulnerability in the protocol.
BTCW (OP)
Copper Member
Full Member
***
Offline Offline

Activity: 193
Merit: 235

Click "+Merit" top-right corner


View Profile
August 30, 2020, 10:57:40 PM
 #4

The smallest transaction that can be relayed is 82 bytes. There is a hard minimum at 82 bytes as that is the non-witness size of a 1 in,  1 out P2WPKH transaction. The limit is there to protect against CVE-2017-12842.

You can shave off 1 byte by using a redeemScript of just OP_TRUE. Then you won't need to push anything else to the stack in the scriptSig.

If you are willing to make an output that only miners can spend, but can still be relayed, then you can create a witness output with an unknown witness version. Currently only segwit v0 is defined, but segwit currently allows up to version 16. Besides v0, only v1 has been proposed - this is taproot. You can use the other witness versions and transactions containing those outputs will still be relayed. The caveat is that those outputs cannot be spent because spending them is non-standard. Only miners can spend them since they aren't consensus invalid. And if you wait too long to spend them, they will become unspendable when that witness version is defined.

So you can replace your P2WPKH output with an unknown witness version and just pad it up to the 82 byte minimum. Furthermore, such an output will also have a bech32 address, and in theory, any wallet that supports segwit can send to that address.



In case you are wondering, I did also try a couple of other weird things to get small transactions. Unfortunately they don't work.

I was able to make a 64 byte transaction using the unknown witness version trick, but because I was trying to spend an output with an unknown witness version, this was non-standard and wasn't accepted by my node.

It is possible to make a 0-of-0 multisig, and Bitcoin does allow bare multisig scriptPubKeys. However the standardness check on multisigs requires at least a 1-of-1, so this didn't work either.

Wow! We have a number of mutual interests Smiley

I didn't know about the 82-byte floor, most fascinating, where can I read about it? My new goal is definitely to broadcast an 82-byte transaction, have it mined and included in a block (the regular way - i.e. not asking miners "please", because that fails the reproducibility test in my book), and being able to spend from wherever the coins end up.

A practical question: In theory, a sigScirpt could be "OP_1" which together with the length byte would be "0151", i.e. 2 bytes. However, I've never gotten this to work in practice. My understanding - please do enlighten me if I'm totally off - is that you must provide both an unlocking code (which in turn must be "push only", i.e. have no other opcodes than those that push items onto the stack and it must furthermore not be nothing, AND the locking code, and further - that the hash of the locking code must correspond to the address you're spending from (i.e. where the txid, or UTXO if you will), points to (otherwise you could spend from all anyone-can-spend-addresses with just "0151", which you can't).

The terminology is a little confusing and somewhat inconsistently used, but is the definition of sigscript that I use is:

<overall length byte><unlocking script><locking script length byte><locking script>

which for my original transaction thus becomes 03 51 01 61

For the record, "61" equals "OP_NOP", i.e. do nothing, so that the unlocking script in my transaction pushes 01 onto the stack, and the locking script does nothing, i.e. leaves it there, so that all of it when executed leaves the stack with a top value of "01", nothing else, which equals "TRUE".

To be redundantly clear: I want to broadcast transactions that are accepted and mined (must thus pass IsStandard() functions), and send to spendable addresses, which is why OP_RETURN or very short P2S (the latter are no longer considered standard) are not the way forward.

Clearly, I can never accomplish this with a cryptographically safe transaction, as there is no room left for signatures or witness programs.

To begin with: are there 82-byte transactions from say 2017 and until now? Or is my 85-byte example some sort of record?

SendBTC.me <<< amazing imitative
achow101
Moderator
Legendary
*
expert
Offline Offline

Activity: 3388
Merit: 6635


Just writing some code


View Profile WWW
August 31, 2020, 12:30:36 AM
Merited by ABCbits (1), Husna QA (1), BTCW (1)
 #5

Please don't. Using transactions below the standard size limit will interfere with fixing a security vulnerability in the protocol.
As long as the tx remains within the standardness rules (and the goal is to do that), the txs shouldn't interfere.

I didn't know about the 82-byte floor, most fascinating, where can I read about it?
There's a comment about it in the source: https://github.com/bitcoin/bitcoin/blob/master/src/validation.cpp#L588

You'll want to look up the CVE to get more info on the attack it protects against.

My new goal is definitely to broadcast an 82-byte transaction, have it mined and included in a block (the regular way - i.e. not asking miners "please", because that fails the reproducibility test in my book), and being able to spend from wherever the coins end up.
Being able to spend the output created might make this impossible to do. With a scriptSig that's already as small as possible, the output is really the only other place you can shrink.

A practical question: In theory, a sigScirpt could be "OP_1" which together with the length byte would be "0151", i.e. 2 bytes. However, I've never gotten this to work in practice. My understanding - please do enlighten me if I'm totally off - is that you must provide both an unlocking code (which in turn must be "push only", i.e. have no other opcodes than those that push items onto the stack and it must furthermore not be nothing, AND the locking code, and further - that the hash of the locking code must correspond to the address you're spending from (i.e. where the txid, or UTXO if you will), points to (otherwise you could spend from all anyone-can-spend-addresses with just "0151", which you can't).
Nope. You can just push the redeemScript and it'll work.

Here's an 82 byte transaction I made on regtest that spends a P2SH output with the redeemScript of OP_TRUE. The output is does the unknown witness thing, so you can't actually spend this output without a miner.
Code:
02000000013f0c4fa2d2ee6cc8ec4a24f1100cf03d6053ee5e50f923867caed8b5e15d903a00000000020151ffffffff01605af4050000000014521200000000000000000000000000000000000000000000

To begin with: are there 82-byte transactions from say 2017 and until now? Or is my 85-byte example some sort of record?
Probably not. I might search the blockchain for the smallest tx, but that'll take a while.

pooya87
Legendary
*
Offline Offline

Activity: 3444
Merit: 10558



View Profile
August 31, 2020, 03:12:10 AM
Last edit: August 31, 2020, 05:38:28 AM by pooya87
Merited by ABCbits (1), BTCW (1)
 #6

you can always go to blockchair block explorer and sort the transactions based on different factors (such as their size) and look at the crazy things other people have done in the past.
there are a bunch of 62 byte transactions (the current smallest size on mainnet blockchain so far) made back in 2015:
https://blockchair.com/bitcoin/transactions?s=size(asc)#f=block_id,hash,time,has_witness,input_count,output_count,size

i wonder if these could have been shrunk down to 60 bytes if the input was spending a pubkey script that were OP_TRUE instead of the signature script being OP_TRUE (so it could be empty) and then the pubkey script of the tx to be replaced by an empty one instead of an OP_RETURN.
edit: it should be possible to create a 60-byte transaction too. here is a 61-byte tx on testnet which does the first part of what i said https://blockchair.com/bitcoin/testnet/transaction/5230030b8b797cd9e9b3e90d12d51d14df7f87f36fa058d6c019e806000905a7

To begin with: are there 82-byte transactions from say 2017 and until now? Or is my 85-byte example some sort of record?
Probably not. I might search the blockchain for the smallest tx, but that'll take a while.
1x 67 byte, 7x 84 byte, and more 85 bytes
https://blockchair.com/bitcoin/transactions?q=time(2017-01-01..)&s=size(asc)#f=block_id,hash,time,has_witness,input_count,output_count,size

.
.BLACKJACK ♠ FUN.
█████████
██████████████
████████████
█████████████████
████████████████▄▄
░█████████████▀░▀▀
██████████████████
░██████████████
████████████████
░██████████████
████████████
███████████████░██
██████████
CRYPTO CASINO &
SPORTS BETTING
▄▄███████▄▄
▄███████████████▄
███████████████████
█████████████████████
███████████████████████
█████████████████████████
█████████████████████████
█████████████████████████
███████████████████████
█████████████████████
███████████████████
▀███████████████▀
█████████
.
achow101
Moderator
Legendary
*
expert
Offline Offline

Activity: 3388
Merit: 6635


Just writing some code


View Profile WWW
August 31, 2020, 04:48:52 AM
 #7

I can't seem to find the transaction, the input is also not available.
on regtest
I wasn't going to burn real money on this, besides the fact that getting my Bitcoin is a pain in the ass.

nc50lc
Legendary
*
Offline Offline

Activity: 2408
Merit: 5594


Self-proclaimed Genius


View Profile
August 31, 2020, 04:52:22 AM
 #8

I can't seem to find the transaction, the input is also not available.
on regtest
I wasn't going to burn real money on this, besides the fact that getting my Bitcoin is a pain in the ass.
Sorry, I missed the "on regtest", thinking of testnet and made a sample testnet transaction myself as another sample:
6e1d378e6f5779dad5da43984924618ba82b93465e74eaa5bf6146d1584e59c8
I was about to edit the post but you've already made a reply.

.
.HUGE.
▄██████████▄▄
▄█████████████████▄
▄█████████████████████▄
▄███████████████████████▄
▄█████████████████████████▄
███████▌██▌▐██▐██▐████▄███
████▐██▐████▌██▌██▌██▌██
█████▀███▀███▀▐██▐██▐█████

▀█████████████████████████▀

▀███████████████████████▀

▀█████████████████████▀

▀█████████████████▀

▀██████████▀▀
█▀▀▀▀











█▄▄▄▄
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
.
CASINSPORTSBOOK
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀▀█











▄▄▄▄█
BTCW (OP)
Copper Member
Full Member
***
Offline Offline

Activity: 193
Merit: 235

Click "+Merit" top-right corner


View Profile
August 31, 2020, 09:16:07 AM
 #9

Please don't. Using transactions below the standard size limit will interfere with fixing a security vulnerability in the protocol.
As long as the tx remains within the standardness rules (and the goal is to do that), the txs shouldn't interfere.

I didn't know about the 82-byte floor, most fascinating, where can I read about it?
There's a comment about it in the source: https://github.com/bitcoin/bitcoin/blob/master/src/validation.cpp#L588

You'll want to look up the CVE to get more info on the attack it protects against.

My new goal is definitely to broadcast an 82-byte transaction, have it mined and included in a block (the regular way - i.e. not asking miners "please", because that fails the reproducibility test in my book), and being able to spend from wherever the coins end up.
Being able to spend the output created might make this impossible to do. With a scriptSig that's already as small as possible, the output is really the only other place you can shrink.

A practical question: In theory, a sigScirpt could be "OP_1" which together with the length byte would be "0151", i.e. 2 bytes. However, I've never gotten this to work in practice. My understanding - please do enlighten me if I'm totally off - is that you must provide both an unlocking code (which in turn must be "push only", i.e. have no other opcodes than those that push items onto the stack and it must furthermore not be nothing, AND the locking code, and further - that the hash of the locking code must correspond to the address you're spending from (i.e. where the txid, or UTXO if you will), points to (otherwise you could spend from all anyone-can-spend-addresses with just "0151", which you can't).
Nope. You can just push the redeemScript and it'll work.

Here's an 82 byte transaction I made on regtest that spends a P2SH output with the redeemScript of OP_TRUE. The output is does the unknown witness thing, so you can't actually spend this output without a miner.
Code:
02000000013f0c4fa2d2ee6cc8ec4a24f1100cf03d6053ee5e50f923867caed8b5e15d903a00000000020151ffffffff01605af4050000000014521200000000000000000000000000000000000000000000

Many thanks! Will read all about the 82-byte limit.

Cool. OK, so I should be able to shave off 1 more byte with sigscript = "020151" (3 bytes). (Out of curiosity, how is this interpreted programmatically, is it the unlocking or locking script that is considered empty? Not that it makes any difference, the net result is the same; "TRUE".)

Since arbitrary scripts are accepted as recipients on the testnet, it is easy to believe you have accomplished something new, only to later discover your new string isn't reproducible on the mainnet.

Will revert if/when I have broadcast something new and shorter on the testnet, that should work on the mainnet. I will not use OP_RETURN due to my own (quite arbitrary) rule that the output must be spendable.

SendBTC.me <<< amazing imitative
BTCW (OP)
Copper Member
Full Member
***
Offline Offline

Activity: 193
Merit: 235

Click "+Merit" top-right corner


View Profile
August 31, 2020, 09:20:03 AM
 #10

To begin with: are there 82-byte transactions from say 2017 and until now? Or is my 85-byte example some sort of record?
Probably not. I might search the blockchain for the smallest tx, but that'll take a while.
1x 67 byte, 7x 84 byte, and more 85 bytes
https://blockchair.com/bitcoin/transactions?q=time(2017-01-01..)&s=size(asc)#f=block_id,hash,time,has_witness,input_count,output_count,size


A fantastic block explorer for these questions. Very good, thanks!

SendBTC.me <<< amazing imitative
BTCW (OP)
Copper Member
Full Member
***
Offline Offline

Activity: 193
Merit: 235

Click "+Merit" top-right corner


View Profile
September 01, 2020, 12:03:12 AM
 #11

Another try:

locking script ="OP_11" = "5b" --> 2NBfBS5XCqbBL1D8gLCFG15S5gPE4LEWBr2
unlockin script ="" #i.e. empty

Sent 0.1 tBTC there

Sigscript "015b" not OK, but "02015b" is - those "double-length bytes" is an annoying feature...

Anyways, this spending was broadcast successfully:

Code:
sendrawtransaction 0100000001627f0684c718602906faff73b62179f042875dfd62e905d6da7faf8f6a7349810100000002015bffffffff0186959800000000001600141ee44a2f2c8d366945ff02676bd608f70a559ea700000000

txid: 0f8ecbf7180ff5b48ac2addc85400b252c64c853b553d86e0c704bbd19829651

But it is only 1 byte shorter compared to the OP tx, due to the damn padding in the sigscript.

Anyways, down to 84 bytes now, and all of it should be reproducible on the mainnet,

I'm not sure I can shave off another 2 whole bytes, to reach the 82-byte target, Please advise!




SendBTC.me <<< amazing imitative
pooya87
Legendary
*
Offline Offline

Activity: 3444
Merit: 10558



View Profile
September 01, 2020, 03:48:50 AM
 #12

Sigscript "015b" not OK, but "02015b" is - those "double-length bytes" is an annoying feature...

it is probably because you haven't learned what they are and what they do, and i'm guessing you are creating all these transactions by hand instead of by code.

there are a bunch of size or lengths in bitcoin specifically in its scripts. a varint or compactint for the size of the entire script which is not part of the script itself but part of the transaction letting us know how many bytes to read to reach the end of the script. here they are 01 for the first and 02 for the second.
you should compute these after you are done writing the script and for example if the script was 254 bytes it becomes 0xfdfe00
https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer

then there is items (bytes) that are supposed to be pushed to the stack. in a P2SH signature script it ends with the redeem script which is 0x5b and since it is one byte you use 0x01 but the same example above if you wanted to push 254 bytes it becomes 0x4cfe
https://en.bitcoin.it/wiki/Script#Constants

.
.BLACKJACK ♠ FUN.
█████████
██████████████
████████████
█████████████████
████████████████▄▄
░█████████████▀░▀▀
██████████████████
░██████████████
████████████████
░██████████████
████████████
███████████████░██
██████████
CRYPTO CASINO &
SPORTS BETTING
▄▄███████▄▄
▄███████████████▄
███████████████████
█████████████████████
███████████████████████
█████████████████████████
█████████████████████████
█████████████████████████
███████████████████████
█████████████████████
███████████████████
▀███████████████▀
█████████
.
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!