Bitcoin uses the same cryptographic concepts we have been discussing in class to achieve a startling result. A decentralized system for financial transactions. Here we will see some of the concepts illustrated with python code.
I learned a lot from the bitcoin paper[1], and a couple of blog entries on raw bitcoin[2] and mining[3].
Bitcoins are chains of digital signatures¶
In [6]:
import sys
sys.path.append("/home/humberto/Documents/class/2015/cyber2/toys/rsa")
In [7]:
import rsa
coin = rsa.RSAPrivateKey(64)
In [8]:
pubcoin = coin.GetPublicKey()
pubcointuple = pubcoin.e, pubcoin.N, "I just made 25BTC"
str(pubcointuple)
Out[8]:
"(5, 141696464709924649492511653706884215967L, 'I just made 25BTC')"
In [9]:
sys.path.append("/home/humberto/anaconda/envs/cyber2/lib/python2.7/site-packages")
In [10]:
import hashlib
from merkletools import MerkleTools
mt = MerkleTools()
pretransactions = [hashlib.sha256(str(pubcointuple)).digest().encode("hex"), "hash of (I send 1BTC to Julio)", "hash of (I send 1BTC to Krystian)"]
In [11]:
es = [rsa.Message.Encode(txn, pubcoin.N).numbers for txn in pretransactions]
es
Out[11]:
[[504630249641664894383901292028508215L, 255505452750972701062293260732479845L, 297972698342949253392120592133534257L, 251245924270104739894930730978326839L, 260612910109979521957662355907149824L], [541975410483518140009349501134663268L, 167152592680311475874442783945748265L], [541975410483518140009349501134663268L, 167152592680311475874443870791234665L, 505887108688943048551933676877774848L]]
In [12]:
txns = [map(lambda c: rsa.modexp(c, coin.d, coin.N), cs) for cs in es]
txns
Out[12]:
[[11908923437035327175078768015796392559L, 30669950496249226377830731094820207129L, 44172961311871811822930654213672565695L, 123172911476233136905979189094163909971L, 43188382834495278323751536059500387592L], [138632599381808143821930476698617978242L, 84649519227353175027207938061705840870L], [138632599381808143821930476698617978242L, 77296456319505086683048755426268217102L, 94716336958858599883100938620782612818L]]
In [13]:
mt.add_leaf(map(str, txns), True)
mt.make_tree()
print "root:", mt.get_merkle_root()
root: cff7e6e572aef613b5d8b6a9521a42439f2f490cf85d82172080a55dd14880d0
In [14]:
mt.get_leaf_count()
Out[14]:
3
In [15]:
proofs = [mt.get_proof(i) for i in range(mt.get_leaf_count())]
proofs
Out[15]:
[[{'right': 'ba6fa378bed988dfade565eccc07abd0937858211bdfe715cc6c2d246f9c88f2'}, {'right': 'ff877cb2ead86f5b377fab86151b10110123af934d5fae453950b9baa2c79810'}], [{'left': 'b486f113d35b809760686228100c3a5a4bc395f918445a2e5e75e3260a595281'}, {'right': 'ff877cb2ead86f5b377fab86151b10110123af934d5fae453950b9baa2c79810'}], [{'left': '929d1d3cc77e2801cef60c48e9dad013ddd24d751c26ed2ef248a6a33140437a'}]]
In [16]:
mt.get_leaf(0)
Out[16]:
'b486f113d35b809760686228100c3a5a4bc395f918445a2e5e75e3260a595281'
In [17]:
import hashlib
In [18]:
check = hashlib.sha256(str(txns[0])).digest().encode("hex")
check
Out[18]:
'b486f113d35b809760686228100c3a5a4bc395f918445a2e5e75e3260a595281'
In [19]:
mt.validate_proof(mt.get_proof(0), check, mt.get_merkle_root())
Out[19]:
True
In [20]:
digits = "0123456789ABCDEF"
nonce = -1
def encode(nonce, digits):
result = ""
while nonce:
result = digits[nonce % len(digits)] + result
nonce /= len(digits)
return result
Blocks form a chain through their hashes.
In [21]:
oldblock = "0 "
digest = mt.get_merkle_root()
block = oldblock + digest
newhash = hashlib.sha256(block).digest().encode("hex")
while not newhash.startswith("00000"):
nonce += 1
newblock = block + encode(nonce, digits)
newhash = hashlib.sha256(newblock).digest().encode("hex")
print "Found nonce:", nonce, newhash
Found nonce: 1215813 000000c8c68e562df43d8bcf9f2d9f44747721f5b914a7094d68ce2419f52631
References¶
- Nakamoto, Satoshi. "Bitcoin: A peer-to-peer electronic cash system." (2008). https://bitcoin.org/bitcoin.pdf
- Shirriff, Ken, Bitcoins the hard way. http://www.righto.com/2014/02/bitcoins-hard-way-using-raw-bitcoin.html
- Shirriff, Ken. Bitcoin mining the hard way. http://www.righto.com/2014/02/bitcoin-mining-hard-way-algorithms.html