Search code examples
transactionsbitcoinecdsa

Signing a Bitcoin Segwit Transaction


To learn more about Bitcoin Transactions, I'm studying the binary and not really using any of the tools like BitcoinTx or Bitcoin-cli. Anyway, I've hit a bit of a snag when trying to sign a segwit transaction. Now this is a simple transaction, one UTXO and one recipient and it's a P2WPKH transaction.

The problem is, for a segwit I don't know what to put in the SigScript field before signing the transaction. The documentation says it should be empty, but that doesn't seem to work.

02000000010a02214430acee2ed509798187210171bb387075ce2c82ef5a73774d6159387500000000 00 ffffffff
018ca1b404000000001976a914906ec1c4804632c0b067e5a2732c41cdf620c4e688ac0000000001000000

The above is the raw transaction, 1 input, 1 output. In the segwit field, I've got a 0x00 byte as indicated. So, I sha256(sha256) the above binary and then create my signed segwit transaction as below:

020000000001010a02214430acee2ed509798187210171bb387075ce2c82ef5a73774d615938750000000017160014d99f1ea19e98d9ed10e5d442be37a44b6b63c477ffffffff 018ca1b404000000001976a914906ec1c4804632c0b067e5a2732c41cdf620c4e688ac 02 4830460221009f5743a2fc62bb9cee292ef79eb3ec3a20a3ed1ec84bdf9e8520592ca1d84f35022100922f887be7283eb0fd73da53efa554e62a589f6e268c0d300ad727791c2f936c 41047d011958b661181242addd300b6d5c51f80d62674555831dd855b34358b57e05fb46477ba167a57b23bf8a492305c0085d8c34aa04d483b7f15a2d551e2ff66200000000

So in the above, I've got my input transaction and in the SigScript I've put a push of 0 followed by a 20byte Hash160 of the public key.

Next, the output transaction, which just has a public key hash with OP_DUP, OP_HASH_160 OP_EQUALVERIFY, OP_CHECKSIG.

Finally comes the signature, that has 02 for 2 parts, 1 being the signature itself (der-encoded) and lastly the public key.

For some reason it says the signature is incorrect and I have no-idea why. Should the SigScript in the transaction actually by NULL before I sign it? Should it be a HASH160 of the wallet's public key that has the funds (like it is for a P2PKH transaction) before I sign it?

Any pointers would be greatly appreciated because I think I'm close, I just need to know what the transaction has to look like, before I sign it.


Solution

  • You need to put the ScriptPubKey on SigScript field for signing purposes. Be very careful with Endianess and Low-High R and S rule on eliptic curve signature.

    Explanation from: https://bitcoin.stackexchange.com/posts/32695/edit

    Step-by-step description:

    We start creating a new transaction which we hash and sign.

    1. Add four-byte version field: 01000000
    2. One-byte varint specifying the number of inputs: 01
    3. 32-byte hash of the transaction from which we want to redeem an output (reverse order): be66e10da854e7aea9338c1f91cd489768d1d6d7189f586d7a3613f2a24d5396
    4. Four-byte field denoting the output index we want to redeem from the transaction with the above hash (counting from zero): 00000000
    5. Now comes the scriptSig. For the purpose of signing the transaction, this is temporarily filled with the scriptPubKey of the output we want to redeem. First we write a one-byte varint which denotes the length of the scriptSig (0x19 = 25 bytes): 19
    6. Then we write the actual scriptSig (which is the scriptPubKey of the output we want to redeem): 76 a9 14 dd6cce9f255a8cc17bda8ba0373df8e861cb866e 88 ac (look to the bottom line line on https://blockchain.info/tx/96534da2f213367a6d589f18d7d6d1689748cd911f8c33a9aee754a80de166be?show_adv=true )
    7. Then we write a four-byte field denoting the sequence. This is currently always set to 0xffffffff: ffffffff
    8. Next comes a one-byte varint containing the number of outputs in our new transaction. We will set this to 1 in this example: 01
    9. We then write an 8-byte field (64 bit integer, little-endian) containing the amount we want to redeem from the specified output. I will set this to the total amount available in the output minus a fee of 0.0001 BTC (128307 - 10000): 23ce010000000000
    10. Then we start writing our transaction's output. We start with a one-byte varint denoting the length of the output script (0x19 or 25 bytes): 19
    11. Then the actual output script: 76 a9 14 a2fd2e039a86dbcf0e1a664729e09e8007f89510 88 ac ( this is transferring funds back to address 1FromKBPAS8MWsk1Yv1Yiu8rJbjfVioBHc )
    12. Then we write the four-byte "lock time" field: 00000000
    13. And at last, we write a four-byte "hash code type" (1 in our case): 01000000

    OK, the result is

    01000000
    01
    be66e10da854e7aea9338c1f91cd489768d1d6d7189f586d7a3613f2a24d5396
    00000000
    19 76 a9 14 dd6cce9f255a8cc17bda8ba0373df8e861cb866e 88 ac
    ffffffff
    01
    23ce010000000000
    19 76 a9 14 a2fd2e039a86dbcf0e1a664729e09e8007f89510 88 ac
    00000000
    01000000
    
    1. Now we double-SHA256 hash this entire structure, which yields the hash 1cde0239b55717cca8003104abc2ec2673d4f6fabea0b74351940e382e88486f

    2. Now we should create ECDSA signature... 1MBngSqZbMydscpzSoehjP8kznMaHAzh9y is a brainwallet of "mrbubbymrbubbymrbubby!", which just happens to encode an address starting in 'MB' (making linking the 2 quite easy; see @WizardOfAussie comment below for phrase origins). Private key in WIF: 5HvofFG7K1e2aeWESm5pbCzRHtCSiZNbfLYXBvxyA57DhKHV4U3

    In hex, the private key is 0ecd20654c2e2be708495853e8da35c664247040c00bd10b9b13e5e86e6a808d. There is a sign (key, digest) method in every crypto lib. It will return an array of bytes. This array will be no more than 72 bytes, and start with hex code 30. Lets imagine that the signature is 3046022100cf4d7571dd47a4d47f5cb767d54d6702530a3555726b27b6ac56117f5e7808fe0221008cbb42233bb04d7f28a715cf7c938e238afde90207e9d103dd9018e12cb7180e To this signature we append the one-byte hash code type: 01. The public key for 1MBngSqZbMydscpzSoehjP8kznMaHAzh9y is: 042daa93315eebbe2cb9b5c3505df4c6fb6caca8b756786098567550d4820c09db988fe9997d049d687292f815ccd6e7fb5c1b1a91137999818d17c73d0f80aef9

    1. We construct the final scriptSig by concatenating: <One-byte script OPCODE containing the length of the DER-encoded signature plus the one-byte hash code type>|< The actual DER-encoded signature plus the one-byte hash code type>|< One-byte script OPCODE containing the length of the public key>|<The actual public key>

    scriptSig will be

    49 3046022100cf4d7571dd47a4d47f5cb767d54d6702530a3555726b27b6ac56117f5e7808fe0221008cbb42233bb04d7f28a715cf7c938e238afde90207e9d103dd9018e12cb7180e 01
    41 042daa93315eebbe2cb9b5c3505df4c6fb6caca8b756786098567550d4820c09db988fe9997d049d687292f815ccd6e7fb5c1b1a91137999818d17c73d0f80aef9
    

    first line is 'push signature concatenated with 01', second line is 'push pubkey'. The length of scriptSig is 140 bytes (0x8c in hex)

    1. We then replace the one-byte, varint length-field from step 5 with the length of the data from step 16. The length is 140 bytes, or 0x8C bytes: 8c

    2. And we replace the actual scriptSig with the data structure constructed in step 16.

    3. We finish off by removing the four-byte hash code type we added in step 13, and we end up with the following stream of bytes, which is the final transaction:

      01000000 01 be66e10da854e7aea9338c1f91cd489768d1d6d7189f586d7a3613f2a24d5396 00000000 8c 49 3046022100cf4d7571dd47a4d47f5cb767d54d6702530a3555726b27b6ac56117f5e7808fe0221008cbb42233bb04d7f28a715cf7c938e238afde90207e9d103dd9018e12cb7180e 01 41 042daa93315eebbe2cb9b5c3505df4c6fb6caca8b756786098567550d4820c09db988fe9997d049d687292f815ccd6e7fb5c1b1a91137999818d17c73d0f80aef9 ffffffff 01 23ce010000000000 19 76 a9 14 a2fd2e039a86dbcf0e1a664729e09e8007f89510 88 ac 00000000