Skip to content

Instantly share code, notes, and snippets.

@bitkevin
Created June 30, 2013 06:52
Show Gist options
  • Save bitkevin/5894156 to your computer and use it in GitHub Desktop.
Save bitkevin/5894156 to your computer and use it in GitHub Desktop.
With Bitcoin 0.7 it's possible to keep your private keys
entirely offline without third party software.
In this example we have two hosts [offline] which is
totally offline and without a copy of the blockchain
and [online] which is a regular online node, both
running bitcoin 0.7.
This example uses the CLI, but it works equally well with
the GUI console interface-- just leave off the "bitcoind"
at the start of every command.
We're going to generate a key on the offline wallet, then
send it 50 BTC with an online wallet, then using the online
wallet draft a transaction to send it back, then sign that
with the offline wallet, and finally announce the signed
transaction into the network using the online wallet.
First generate an address offline:
[offline]$ bitcoind getnewaddress
n1gqLjZbRH1biT5o4qiVMiNig8wcCPQeB9
Then, send it 50 coin:
[online]$ bitcoind sendtoaddress n1gqLjZbRH1biT5o4qiVMiNig8wcCPQeB9 50
a9d4599e15b53f3eb531608ddb31f48c695c3d0b3538a6bda871e8b34f2f430c
Now, grab the transaction that was paying it. We'll need the txid, and the
scriptpubkey paying our offline wallet.
[online]$ bitcoind getrawtransaction a9d4599e15b53f3eb531608ddb31f48c695c3d0b3538a6bda871e8b34f2f430c 1
{
"hex" : "0100000001344630cbff61fbc362f7e1ff2f11a344c29326e4ee96e787dc0d4e5cc02fd069000000004a493046022100ef89701f460e8660c80808a162bbf2d676f40a331a243592c36d6bd1f81d6bdf022100d29c072f1b18e59caba6e1f0b8cadeb373fd33a25feded746832ec179880c23901ffffffff0100f2052a010000001976a914dd40dedd8f7e37466624c4dacc6362d8e7be23dd88ac00000000",
"txid" : "a9d4599e15b53f3eb531608ddb31f48c695c3d0b3538a6bda871e8b34f2f430c",
"version" : 1,
"locktime" : 0,
"vin" : [
{
"txid" : "69d02fc05c4e0ddc87e796eee42693c244a3112fffe1f762c3fb61ffcb304634",
"vout" : 0,
"scriptSig" : {
"asm" : "3046022100ef89701f460e8660c80808a162bbf2d676f40a331a243592c36d6bd1f81d6bdf022100d29c072f1b18e59caba6e1f0b8cadeb373fd33a25feded746832ec179880c23901",
"hex" : "493046022100ef89701f460e8660c80808a162bbf2d676f40a331a243592c36d6bd1f81d6bdf022100d29c072f1b18e59caba6e1f0b8cadeb373fd33a25feded746832ec179880c23901"
},
"sequence" : 4294967295
}
],
"vout" : [
{
"value" : 50.00000000,
"n" : 0,
"scriptPubKey" : {
"asm" : "OP_DUP OP_HASH160 dd40dedd8f7e37466624c4dacc6362d8e7be23dd OP_EQUALVERIFY OP_CHECKSIG",
"hex" : "76a914dd40dedd8f7e37466624c4dacc6362d8e7be23dd88ac",
"reqSigs" : 1,
"type" : "pubkeyhash",
"addresses" : [
"n1gqLjZbRH1biT5o4qiVMiNig8wcCPQeB9"
]
}
}
]
}
And lets get an address to return those coins to:
[online]$ bitcoind getnewaddress
mkZBYBiq6DNoQEKakpMJegyDbw2YiNQnHT
Now, from our online node we're going to draft the transaction to
return the coin from the offline wallet to the online one:
[online]$ bitcoind createrawtransaction '[{"txid":"a9d4599e15b53f3eb531608ddb31f48c695c3d0b3538a6bda871e8b34f2f430c","vout":0}]' '{"mkZBYBiq6DNoQEKakpMJegyDbw2YiNQnHT":50}'
01000000010c432f4fb3e871a8bda638350b3d5c698cf431db8d6031b53e3fb5159e59d4a90000000000ffffffff0100f2052a010000001976a9143744841e13b90b4aca16fe793a7f88da3a23cc7188ac00000000
One the offline wallet we decode the transaction to validate that its doing
what we expect. Note: Since we don't have the input transaction we don't
know the input value and this txn could be paying a ton of change out
to fees.
[offline]$ bitcoind decoderawtransaction 01000000010c432f4fb3e871a8bda638350b3d5c698cf431db8d6031b53e3fb5159e59d4a90000000000ffffffff0100f2052a010000001976a9143744841e13b90b4aca16fe793a7f88da3a23cc7188ac00000000
{
"txid" : "d9f33ed2740eef77e40e72b692c4cf1feb6ab10d8adaaf27eb394fa5064b1160",
"version" : 1,
"locktime" : 0,
"vin" : [
{
"txid" : "a9d4599e15b53f3eb531608ddb31f48c695c3d0b3538a6bda871e8b34f2f430c",
"vout" : 0,
"scriptSig" : {
"asm" : "",
"hex" : ""
},
"sequence" : 4294967295
}
],
"vout" : [
{
"value" : 50.00000000,
"n" : 0,
"scriptPubKey" : {
"asm" : "OP_DUP OP_HASH160 3744841e13b90b4aca16fe793a7f88da3a23cc71 OP_EQUALVERIFY OP_CHECKSIG",
"hex" : "76a9143744841e13b90b4aca16fe793a7f88da3a23cc7188ac",
"reqSigs" : 1,
"type" : "pubkeyhash",
"addresses" : [
"mkZBYBiq6DNoQEKakpMJegyDbw2YiNQnHT"
]
}
}
]
}
If we're happy, we'll sign. We need to provide the scriptpubkey of the
inputs we're signing so our offline wallet knows which of its keys
to use.
[offline]$ bitcoind signrawtransaction 01000000010c432f4fb3e871a8bda638350b3d5c698cf431db8d6031b53e3fb5159e59d4a90000000000ffffffff0100f2052a010000001976a9143744841e13b90b4aca16fe793a7f88da3a23cc7188ac00000000 '[{"txid":"a9d4599e15b53f3eb531608ddb31f48c695c3d0b3538a6bda871e8b34f2f430c","vout":0,"scriptPubKey":"76a914dd40dedd8f7e37466624c4dacc6362d8e7be23dd88ac"}]'
{
"hex" : "01000000010c432f4fb3e871a8bda638350b3d5c698cf431db8d6031b53e3fb5159e59d4a9000000006b48304502201123d735229382f75496e84ae5831871796ef78726805adc2c6edd36d23e7210022100faceab822a4943309c4b6b61240ae3a9e18ed90a75117c5dc4bfd8f7e17a21d301210367ce0a1c3b3e84cece6dad1a181d989d8e490b84f5431a1f778a88b284c935e6ffffffff0100f2052a010000001976a9143744841e13b90b4aca16fe793a7f88da3a23cc7188ac00000000",
"complete" : true
}
Then we'll carry the transaction over to the online wallet and
announce it:
[online]$ bitcoind sendrawtransaction 01000000010c432f4fb3e871a8bda638350b3d5c698cf431db8d6031b53e3fb5159e59d4a9000000006b48304502201123d735229382f75496e84ae5831871796ef78726805adc2c6edd36d23e7210022100faceab822a4943309c4b6b61240ae3a9e18ed90a75117c5dc4bfd8f7e17a21d301210367ce0a1c3b3e84cece6dad1a181d989d8e490b84f5431a1f778a88b284c935e6ffffffff0100f2052a010000001976a9143744841e13b90b4aca16fe793a7f88da3a23cc7188ac00000000
7822dda72d9bf421d2f3eedc678bf58c6e4c10cdd047b9e137559ad384933ef5
And we can see the online wallet has been paid:
[online]$ bitcoind listtransactions "" 1
[
{
"account" : "",
"address" : "mkZBYBiq6DNoQEKakpMJegyDbw2YiNQnHT",
"category" : "receive",
"amount" : 50.00000000,
"confirmations" : 0,
"txid" : "7822dda72d9bf421d2f3eedc678bf58c6e4c10cdd047b9e137559ad384933ef5",
"time" : 1344221517
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment