0

Being inspired by the thread (Redeeming a raw transaction step by step example required) I wanted to understand transaction signatures on the byte level.
So I created my own Linux scripts that:

  • generate key pairs
  • accumulate all the necessary bytes that a raw transaction needs
  • leverage OpenSSL to sign the transactions

Everything that deals with private keys I do on an offline computer, while I look at the blockchain explorer on the screen of a different, online system.
For my test transaction, I wanted to redeem one utxo of an address that I control on mainnet, and send some satoshis (just above the 'dust' level) to some other addresses using P2PKH. Here is the transaction that I created and signed manually:

{
    "version": 1,
    "locktime": 0,
    "ins": [
            {
                    "n": 1,
                    "script": {
                            "asm": "304402200c441b33dc180ec93e1df07df575399f74112dbf4a0a200151c9c4f1afc7c71e02200fc2fcf42847d5c504f06edef7b8fa81b092e7b8b00169d7f8868a02da6ad12401 02dece727c6ddde3140abfcc554ffe50768ab29faa7439c411772fe3c7b93f7cb2",
                            "hex": "47304402200c441b33dc180ec93e1df07df575399f74112dbf4a0a200151c9c4f1afc7c71e02200fc2fcf42847d5c504f06edef7b8fa81b092e7b8b00169d7f8868a02da6ad124012102dece727c6ddde3140abfcc554ffe50768ab29faa7439c411772fe3c7b93f7cb2"
                    },
                    "sequence": 4294967295,
                    "txid": "127ea67612d6e217f99b2b28cc9f8347eb518f99c45102f925774ad8f4958d0f",
                    "witness": []
            }
    ],
    "outs": [
            {
                    "script": {
                            "addresses": [
                                    "1HangpEdoDsSe5i3n7DQNbYie65PGGmPcq"
                            ],
                            "asm": "OP_DUP OP_HASH160 b5e5e05c83c470ffd21c3330fb99a6a0101351ad OP_EQUALVERIFY OP_CHECKSIG",
                            "hex": "76a914b5e5e05c83c470ffd21c3330fb99a6a0101351ad88ac"
                    },
                    "value": 800
            },
            {
                    "script": {
                            "addresses": [
                                    "1HaXuSmR7PXhR4GCcyvGC7USYDuDjw6FHw"
                            ],
                            "asm": "OP_DUP OP_HASH160 b5d9896cc07a30e1d739097df0c1d47181cbbe75 OP_EQUALVERIFY OP_CHECKSIG",
                            "hex": "76a914b5d9896cc07a30e1d739097df0c1d47181cbbe7588ac"
                    },
                    "value": 900
            }
    ],
    "hash": "18d7100c870deb63dec258282f5ff150ebc64e4497d107073503fb4343f4810d",
    "txid": "18d7100c870deb63dec258282f5ff150ebc64e4497d107073503fb4343f4810d"
}

... which corresponds to hex representation 01000000010f8d95f4d84a7725f90251c4998f51eb47839fcc282b9bf917e2d61276a67e12010000006a47304402200c441b33dc180ec93e1df07df575399f74112dbf4a0a200151c9c4f1afc7c71e02200fc2fcf42847d5c504f06edef7b8fa81b092e7b8b00169d7f8868a02da6ad124012102dece727c6ddde3140abfcc554ffe50768ab29faa7439c411772fe3c7b93f7cb2ffffffff0220030000000000001976a914b5e5e05c83c470ffd21c3330fb99a6a0101351ad88ac84030000000000001976a914b5d9896cc07a30e1d739097df0c1d47181cbbe7588ac00000000

Electrum has a menu item to 'load transaction by text', what I did with my hex string. It displayed the result correctly as a "transaction unrelated to your wallet" because I had not imported the private key yet. Electrum offered me the option to broadcast the transaction, but I decided not to (*) because I wanted to compare the manually created transaction with the transaction that Electrum would generate when I use their UI features.
(*) I later broadcast my manual transaction via blockchain.com
So, in order to be able to compare, I imported the private key into Electrum and created a transaction with identical parameters (using the 'Pay to many' feature). Here is the transaction that Electrum created:

{
    "version": 2,
    "locktime": 636848,
    "ins": [
            {
                    "n": 1,
                    "script": {
                            "asm": "3045022100fa7033d292275ebcd4d8fdf38d6b76461ba4a9330df3b21cf5e72f25f08938c802207268e19442c1d3e0ff9850cd6f500985260c250e18d71976093475bd61180ebb01 02dece727c6ddde3140abfcc554ffe50768ab29faa7439c411772fe3c7b93f7cb2",
                            "hex": "483045022100fa7033d292275ebcd4d8fdf38d6b76461ba4a9330df3b21cf5e72f25f08938c802207268e19442c1d3e0ff9850cd6f500985260c250e18d71976093475bd61180ebb012102dece727c6ddde3140abfcc554ffe50768ab29faa7439c411772fe3c7b93f7cb2"
                    },
                    "sequence": 4294967294,
                    "txid": "127ea67612d6e217f99b2b28cc9f8347eb518f99c45102f925774ad8f4958d0f",
                    "witness": []
            }
    ],
    "outs": [
            {
                    "script": {
                            "addresses": [
                                    "1HangpEdoDsSe5i3n7DQNbYie65PGGmPcq"
                            ],
                            "asm": "OP_DUP OP_HASH160 b5e5e05c83c470ffd21c3330fb99a6a0101351ad OP_EQUALVERIFY OP_CHECKSIG",
                            "hex": "76a914b5e5e05c83c470ffd21c3330fb99a6a0101351ad88ac"
                    },
                    "value": 800
            },
            {
                    "script": {
                            "addresses": [
                                    "1HaXuSmR7PXhR4GCcyvGC7USYDuDjw6FHw"
                            ],
                            "asm": "OP_DUP OP_HASH160 b5d9896cc07a30e1d739097df0c1d47181cbbe75 OP_EQUALVERIFY OP_CHECKSIG",
                            "hex": "76a914b5d9896cc07a30e1d739097df0c1d47181cbbe7588ac"
                    },
                    "value": 900
            }
    ],
    "hash": "0f33ae7fc5ca788351a4b571083cf0fa8cbb37afe0206260b02c4c889c05c099",
    "txid": "0f33ae7fc5ca788351a4b571083cf0fa8cbb37afe0206260b02c4c889c05c099"
}

... which corresponds to hex representation 02000000010f8d95f4d84a7725f90251c4998f51eb47839fcc282b9bf917e2d61276a67e12010000006a47304402200dd93baf0a38e4a352a7029c2a37a9bb8ef06bc32ab33fabb8278c6733193e4a02203393c4f5b73345a2a76694de9dff429d65b4de77581601ccc748c642a0dac308012102dece727c6ddde3140abfcc554ffe50768ab29faa7439c411772fe3c7b93f7cb2feffffff0220030000000000001976a914b5e5e05c83c470ffd21c3330fb99a6a0101351ad88ac84030000000000001976a914b5d9896cc07a30e1d739097df0c1d47181cbbe7588ace5b70900

And here comes my question:
When I compare the 2 decoded transactions, I get the following differences:

~/$ diff tx-manual tx-electrum 
2,3c2,3
<   "version": 1,
<   "locktime": 0,
---
>   "version": 2,
>   "locktime": 636848,
8,9c8,9
<               "asm": "304402200c441b33dc180ec93e1df07df575399f74112dbf4a0a200151c9c4f1afc7c71e02200fc2fcf42847d5c504f06edef7b8fa81b092e7b8b00169d7f8868a02da6ad12401 02dece727c6ddde3140abfcc554ffe50768ab29faa7439c411772fe3c7b93f7cb2",
<               "hex": "47304402200c441b33dc180ec93e1df07df575399f74112dbf4a0a200151c9c4f1afc7c71e02200fc2fcf42847d5c504f06edef7b8fa81b092e7b8b00169d7f8868a02da6ad124012102dece727c6ddde3140abfcc554ffe50768ab29faa7439c411772fe3c7b93f7cb2"
---
>               "asm": "3045022100fa7033d292275ebcd4d8fdf38d6b76461ba4a9330df3b21cf5e72f25f08938c802207268e19442c1d3e0ff9850cd6f500985260c250e18d71976093475bd61180ebb01 02dece727c6ddde3140abfcc554ffe50768ab29faa7439c411772fe3c7b93f7cb2",
>               "hex": "483045022100fa7033d292275ebcd4d8fdf38d6b76461ba4a9330df3b21cf5e72f25f08938c802207268e19442c1d3e0ff9850cd6f500985260c250e18d71976093475bd61180ebb012102dece727c6ddde3140abfcc554ffe50768ab29faa7439c411772fe3c7b93f7cb2"
11c11
<           "sequence": 4294967295,
---
>           "sequence": 4294967294,
38,39c38,39
<   "hash": "18d7100c870deb63dec258282f5ff150ebc64e4497d107073503fb4343f4810d",
<   "txid": "18d7100c870deb63dec258282f5ff150ebc64e4497d107073503fb4343f4810d"
---
>   "hash": "0f33ae7fc5ca788351a4b571083cf0fa8cbb37afe0206260b02c4c889c05c099",
>   "txid": "0f33ae7fc5ca788351a4b571083cf0fa8cbb37afe0206260b02c4c889c05c099"

Who can explain me the differences (or point me to the appropriate BIP) and why does Electrum use them? I'm aware of the fact that the signatures are not deterministic (EDIT: Following the comment of @Coding Enthusiast, Electrum's signatures are deterministic, but mine are not) and must consequently differ, and thus the hash/txid must differ as well. But what about version, locktime and the significance of the e5b70900 suffix after the last scriptpubkey (see hex representation of the Electrum tx)?

  • The signatures produced by Electrum are deterministic (uses RFC-6979). – Coding Enthusiast Jul 1 at 10:53
1
  • The version number is sort of arbitrary and up to the client, so long as the number chosen is valid.

  • The nLockTime is usually set to the current block height in modern wallets, this is a simple protection against a specific issue in Bitcoin called "fee sniping", where it is more economical to orphan other people's blocks to steal the fee income than it is to mine your own new one at a later height.

  • e5b70900 is the nLockTime, meaning a block height of 636901. See the protocol documentation.

| improve this answer | |
  • Perfect, that clarifies my questions, thanks. – citizenfu Jul 1 at 9:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.