Thursday, October 16, 2014

Interactive session with Electrum

I recently had the opportunity to teach telecommunication engineering graduates at ICAI the fundamentals of Bitcoin in two sessions (thanks Javier and Rafael for the opportunity). In the first session I talked about the fundamentals of Bitcoin (elliptic curves, transactions and the blockchain), following the material in the book.

I wanted the second session to be practical, so I decided to tinker with the Electrum wallet to drive home some of the Bitcoin transactions concepts introduced in the theoretical session. I decided to go with Electrum over Bitcoin Core because it is lightweight: installation and setup is faster as there is not need to download the blockchain. On the other hand, Bitcoin Core has a lot of functionality readily available to explore the blockchain. A third session on blockchain exploration using Bitcoin Core would be the natural next step.

After loading the wallet with some Bitcoin, we turned to the console view of Electrum. First we checked the addresses available:

>> listaddresses()
[
"18tc1LCXMSAGPziTk3HuUKKUQ286uyiMd7",
"1Jc4645oAT1T4b11aBVFL84ejVsmWkKs1n",
"1FwX6t96ab2KKuMHehRF3CR1K3mtxCVtXo",
"1Chp3HR94Z7ZsjG9nHFhz5BPNrjypoiHw5",
"19DCsPuYcJ69p8Hfk2RsXrfSQTFQkBbL1S"
]

These are the addresses generated by Electrum after the 12 word mnemonic code. This mnemonic code can be visualized using the command getseed:

>> getseed()
{
"mnemonic": "unable beard giant feather nobody special pants also stop decide hallway slide",
"seed": "d95a9af9f0e3241bc778909fd4f7eebb",
"version": 4
}

To retrieve the private key associated with a public key we can use the command dumpprivkey:

>> dumpprivkey("1CaPam1wUfJttt5Gkd71wzifVdjxrE9W7o")
[
"5JxQWPa2sqxBfyyyFhRKdQFKRb47FNVuhBed7YtVg5xFada4UC1"
]


Now, lets see what is the balance of our wallet:

>> getbalance()
{
"confirmed": "0.001"
}

And the unspent transaction outputs where this balance comes from:

>> listunspent()
[
{
"address": "18tc1LCXMSAGPziTk3HuUKKUQ286uyiMd7",
"coinbase": false,
"height": 0,
"is_pubkey": false,
"prevout_hash": "1c27a5ec75e4e4367f0074edded0659d33b86d52dc8683086aa248716f0261da",
"prevout_n": 0,
"scriptPubKey": "76a914568b50da42f77d267a037c5dc9ad90ff863af0d488ac",
"value": "0.001"
}
]

There is a bunch of information here, aside from the address recipient of the funds ("18tc1...") and the amount (0.001).

Notice the scriptPubKey of the transaction: "76a91...". This is the computational puzzle that anyone wishing to spend this transaction output must solve, which in this case means signing with the private key associated with the address "18tc1...".

Also, notice the hash of the transaction, that serves as the transaction id: "1c27a...". A following transaction that spends this transaction would reference this hash.

Let's go ahead and create another transaction spending 0.5 mBTC to address "1Jc46...". To achieve this, we have first to create a transaction (using the createrawtransaction command), then request Electrum to sign it (using the signrawtransaction command), and finally publish it to the blockchain (using the sendrawtransaction command). Of course, these three functions are performed by Electrum when sending bitcoins through the GUI, but it is more instructive (and fun :) ) to perform them by hand:


>> tx = wallet.make_unsigned_transaction([("1Jc4645oAT1T4b11aBVFL84ejVsmWkKs1n", 50000)], None, None, None)

This creates a transaction sending 0.5 mBTC to address "1Jc46...". Electrum chooses the unspent transaction outputs to create the transaction. The decision is straightforward in this case as there is only one unspent transaction output available in the wallet. Lets see the transaction created by Electrum:

>> decoderawtransaction(tx.raw)
{
"inputs": [
{
"address": null,
"prevout_hash": "1c27a5ec75e4e4367f0074edded0659d33b86d52dc8683086aa248716f0261da",
"prevout_n": 0,
"sequence": 4294967295,
"signatures": []
}
],
"lockTime": 0,
"outputs": [
{
"address": "1Jc4645oAT1T4b11aBVFL84ejVsmWkKs1n",
"is_pubkey": false,
"prevout_n": 0,
"scriptPubKey": "76a914c11b46240cb97ad18fd08e472c299296324819de88ac",
"value": 50000
},
{
"address": "15AuBAcN96nDH3FXZFtG3m5ySfG85w5qJ9",
"is_pubkey": false,
"prevout_n": 1,
"scriptPubKey": "76a9142dbfccee75eaed84d180d800499ceab579fbd0c288ac",
"value": 30000
}
],
"version": 1
}

The transaction has one input (the only unspent transaction output in the wallet), with transaction id "1c27a...", and two outputs:

"1Jc46...": 0.0005
"15AuB...": 0.0003

Where the values in the transactions are expressed, as is standard, in satoshis (1 satoshi = 10e-8 bitcoins = 0.00000001 bitcoins). Although we only wanted to send bitcoins to the address "1Jc46...", Electrum creates a transaction with two outputs. The reason is that all transaction outputs must be fully spent. Therefore, Electrum sends the requested 0.5 mBTC to addess "1Jc46...", and the rest (0.3 mBTC) to a new address in the wallet. Why send the change to a new address and not the original address "18tc1..."? Electrum by default does not reuse addresses, to increase privacy. Why 0.3 mBTC, where are the other 0.2 mBTC? These are the fees left to the miners.

Also note that the signature to the input is set to null, thus the transaction is not finalized and cannot be send yet. To finalize it, lets create a list with the private keys associated with the addresses with associated unspent funds:

>> public = map(lambda x:x.get('address'), listunspent())
>> public
['18tc1LCXMSAGPziTk3HuUKKUQ286uyiMd7']
>> private = [pr[0] for pr in dumpprivkeys( public )]
>> private
['5JxQWPa2sqxBfyyyFhRKdQFKRb47FNVuhBed7YtVg5xFada4UC1']

The private key "5JxQW..." corresponds to the address "18tc1...". We can now sign the transaction with this private key:

>> txsigned = signrawtransaction(tx.raw, tx.get_input_info(), private)

The variable txsigned contains the signed transaction:

>> txsigned.raw
"0100000001da61026f7148a26a088386dc526db8339d65d0deed74007f36e4e475eca5271c000000008b483045022100a83c4163b62573625e919cf440243365a0a2c4ceb2ca3c51727928786b4e394b02206379678a8e8e76e85dcd8472b86197bc5f28ede3a34ed6bda6c5312736ee005d014104786afa5fa718aa563d51eb305ccf097359145fa99e389484e69c3aa4617786a936da6837e2890448918f4d5b1cbfe132b9e210e0a3b43a2fd766ffe7d7f4c7e7ffffffff0230750000000000001976a9142dbfccee75eaed84d180d800499ceab579fbd0c288ac50c30000000000001976a914c11b46240cb97ad18fd08e472c299296324819de88ac00000000"

The part in bold (76a9142dbfccee75eaed84d180d800499ceab579fbd0c288ac) is the signature to the unspent transaction output. Finally, lets send the signed transaction to the network:

>> sendrawtransaction(txsigned.raw)
"65c2d3d164b36b9926705069043ab8d40df6187b023791d7ee53900aad4486ad"

The response to the sendrawtransaction command is the transaction id: "65c2d...". Finally, lets take a look at the list of unspent transaction outputs again:

>> listunspent()
[
{
"address": "15AuBAcN96nDH3FXZFtG3m5ySfG85w5qJ9",
"coinbase": false,
"height": 0,
"is_pubkey": false,
"prevout_hash": "65c2d3d164b36b9926705069043ab8d40df6187b023791d7ee53900aad4486ad",
"prevout_n": 0,
"scriptPubKey": "76a9142dbfccee75eaed84d180d800499ceab579fbd0c288ac",
"value": "0.0003"
},
{
"address": "1Jc4645oAT1T4b11aBVFL84ejVsmWkKs1n",
"coinbase": false,
"height": 0,
"is_pubkey": false,
"prevout_hash": "65c2d3d164b36b9926705069043ab8d40df6187b023791d7ee53900aad4486ad",
"prevout_n": 1,
"scriptPubKey": "76a914c11b46240cb97ad18fd08e472c299296324819de88ac",
"value": "0.0005"
}
]

As expected there are now two addresses with associated unspent funds: "1Jc46..." with 0.5 mBTC and the change address "15AuB..." with 0.3 mBTC.

Of course, all this could have been easily accomplished through the GUI:




Disclaimer: products and services mentioned in this post are for illustrative purposes only, and their inclusion does not constitute and endorsement by the author. This material is intended for general information purposes only and does not constitute investment, legal or tax advice.