Imagine yourself to be a University Dean in the position of creating a new course on blockchains. To which department would you assign the course?
In fact, any of these departments would be appropriate.
Blockchains are both technological and social movements, yet very few people have both backgrounds.
Blockchain is much more than a technology, it is also a culture and community that is passionate about creating a more equitable world through decentralization.
We are now entering a radical evolution of how we interact and trade because, for the first time, we can lower uncertainty not just with political and economic institutions but with technology alone. Bettina Warburg
The Crypto Anarchist Manifesto by Timothy C. May dates back to mid-1988 and was distributed to some like-minded techno-anarchists at the Crypto ’88 conference:
Combined with emerging information markets, crypto anarchy will create a liquid market for any and all material which can be put into words and pictures. Timothy C. May, Crypto Anarchist Manifesto, 1988
The following excerpt from the Cypherpunk Manifesto by Eric Hughes (1993) is particularly telling since it contains, 30 years before, all ingredients of modern blockchain technology:
We the Cypherpunks are dedicated to building anonymous systems. We are defending our privacy with cryptography, with anonymous mail forwarding systems, with digital signatures, and with electronic money. […] Cypherpunks write code. We know that software can’t be destroyed and that a widely dispersed system can’t be shut down. Eric Hughes, Cypherpunk Manifesto, 1993
Haber and Stornetta were trying to deal with the epistemological problem of truth in the digital age:
The prospect of a world in which all text, audio, picture and video documents are in digital form on easily modifiable media raises the issue of how to certify when a document was created or last changed. The problem is to time-tamp the data, not the medium. Haber and Stornetta, How to Time-Stamp a Digital Document, 1991
In particular, they started from two questions:
The numerous components of blockchain technology can make it challenging to understand.
However, each component can be described simply and used as a building block to understand the larger complex system.
The building blocks of a blockchain are… blocks.
A block is a container for data
In its simplest form it contains:
an identification number
a timestamp of block creation
a bunch of data (usually, transactions)
the genesis block of Bitcoin blockchain
the genesis block of Ethereum blockchain
genesis_block = list(number = 0, timestamp = "2009-01-03 18:15:05", data = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks")
The ideal cryptographic hash function has five main properties:
# load library library(digest) # hash a string digest("Così tra questa immensità s'annega il pensier mio: e il naufragar m'è dolce in questo mare", "sha256")
## [1] "721956f9e4d4a31524ec94bc9926445c81228b96129132745a362eca8d016154"
# hash a slightly different string digest("Così tra questa infinità s'annega il pensier mio: e il naufragar m'è dolce in questo mare", "sha256")
## [1] "0095d410ee1935a163891970ee2606f2031238ac7adf839fe02d3353162cf5a0"
mine
that mines and returns a new block given the previous block. The function receives as parameteres the previous block and a flag genesis
that is TRUE if and only if the block to mint is the genesis block. The new block has the following components:
number
, the number of the blocktimestamp
, the time of block creationdata
, a string saying the number of the blockparent_hash
, the hash of the parent blockhash
, the hash of the current blockchain
that given a positive number creates and returns a blockchain with that number of blocks using the mine
function.mine <- function(previous_block, genesis = FALSE){ if (genesis) { # define genesis block new_block <- list(number = 0, timestamp = Sys.time(), data = "I'm the genesis block", parent_hash = "0") } else { # create new block current_number = previous_block$number + 1 new_block <- list(number = current_number, timestamp = Sys.time(), data = paste0("I'm block ", current_number), parent_hash = previous_block$hash) } # add hash new_block$hash <- digest(new_block, "sha256") return(new_block) }
chain = function(nblocks) { # mine genesis block block_genesis <- mine(NULL, TRUE) # first block is the genesis block blockchain <- list(block_genesis) if (nblocks >= 2) { # add new blocks to the chain for (i in 2:nblocks){ blockchain[[i]] <- mine(blockchain[[i-1]], FALSE) } } return(blockchain) }
chain(nblocks = 3)
## [[1]] ## [[1]]$number ## [1] 0 ## ## [[1]]$timestamp ## [1] "2022-05-20 09:15:25 CEST" ## ## [[1]]$data ## [1] "I'm the genesis block" ## ## [[1]]$parent_hash ## [1] "0" ## ## [[1]]$hash ## [1] "c294f083ac56ea7210d67c994db391dccd9e5f5fb99d08b0a360040fb27fe29e" ## ## ## [[2]] ## [[2]]$number ## [1] 1 ## ## [[2]]$timestamp ## [1] "2022-05-20 09:15:25 CEST" ## ## [[2]]$data ## [1] "I'm block 1" ## ## [[2]]$parent_hash ## [1] "c294f083ac56ea7210d67c994db391dccd9e5f5fb99d08b0a360040fb27fe29e" ## ## [[2]]$hash ## [1] "5217e98bcb2acfe3a07b3e9db6f61329e094f0bb0df35639b1884ff25ebb875d" ## ## ## [[3]] ## [[3]]$number ## [1] 2 ## ## [[3]]$timestamp ## [1] "2022-05-20 09:15:25 CEST" ## ## [[3]]$data ## [1] "I'm block 2" ## ## [[3]]$parent_hash ## [1] "5217e98bcb2acfe3a07b3e9db6f61329e094f0bb0df35639b1884ff25ebb875d" ## ## [[3]]$hash ## [1] "69d78056ba914d1da9e6b2d828e9120fc50c08b60dd2e18f6e52164516dead3b"
proof_of_work
that given a block and a difficulty number solves the proof of work for the block with that difficulty and adds the found nonce and hash to the returned blockmine
and chain
functions to work with the proof of work functionproof_of_work = function(block, difficulty) { block$nonce <- 0 block$hash = digest(block, "sha256") zero = paste(rep("0", difficulty), collapse="") while(substr(block$hash, 1, difficulty) != zero) { block$nonce = block$nonce + 1 block$hash = digest(block, "sha256") } return(block) }
proof_of_work(genesis_block, 1)
## $number ## [1] 0 ## ## $timestamp ## [1] "2009-01-03 18:15:05" ## ## $data ## [1] "The Times 03/Jan/2009 \n Chancellor on brink of second bailout for banks" ## ## $nonce ## [1] 1 ## ## $hash ## [1] "00ef85cbfa77651a0a6427b6c46b3c2b6459e5f20a3f4ad20b89ef391d7bd798"
proof_of_work(genesis_block, 2)
## $number ## [1] 0 ## ## $timestamp ## [1] "2009-01-03 18:15:05" ## ## $data ## [1] "The Times 03/Jan/2009 \n Chancellor on brink of second bailout for banks" ## ## $nonce ## [1] 1 ## ## $hash ## [1] "00ef85cbfa77651a0a6427b6c46b3c2b6459e5f20a3f4ad20b89ef391d7bd798"
proof_of_work(genesis_block, 3)
## $number ## [1] 0 ## ## $timestamp ## [1] "2009-01-03 18:15:05" ## ## $data ## [1] "The Times 03/Jan/2009 \n Chancellor on brink of second bailout for banks" ## ## $nonce ## [1] 8247 ## ## $hash ## [1] "00089cd735e72ecc00173e16086ff6dcfb090d76a87c17035dadd8d933202e9e"
proof_of_work(genesis_block, 4)
## $number ## [1] 0 ## ## $timestamp ## [1] "2009-01-03 18:15:05" ## ## $data ## [1] "The Times 03/Jan/2009 \n Chancellor on brink of second bailout for banks" ## ## $nonce ## [1] 184240 ## ## $hash ## [1] "0000b99f1fe7172de3ea0ee1bcb232f5d75336d999af9894396714ba881d5823"
mine <- function(previous_block, difficulty = 3, genesis = FALSE){ if (genesis) { # define genesis block new_block <- list(number = 0, timestamp = Sys.time(), data = "I'm the genesis block", parent_hash = "0") } else { # create new block current_number <- previous_block$number + 1 new_block <- list(number = current_number, timestamp = Sys.time(), data = paste0("I'm block ", current_number), parent_hash = previous_block$hash) } # add nonce and hash with proof of work new_block <- proof_of_work(new_block, difficulty) return(new_block) }
chain = function(nblocks, difficulty = 3) { # mine genesis block block_genesis = mine(NULL, difficulty, TRUE) # first block is the genesis block blockchain <- list(block_genesis) if (nblocks >= 2) { # add new blocks to the chain for (i in 2:nblocks){ blockchain[[i]] <- mine(blockchain[[i-1]], difficulty) } } return(blockchain) }
chain(nblocks = 3)
## [[1]] ## [[1]]$number ## [1] 0 ## ## [[1]]$timestamp ## [1] "2022-05-20 09:15:32 CEST" ## ## [[1]]$data ## [1] "I'm the genesis block" ## ## [[1]]$parent_hash ## [1] "0" ## ## [[1]]$nonce ## [1] 3476 ## ## [[1]]$hash ## [1] "000cd4fd973996089cea1548897b5cc5e94e00cf5f7cd96b6854e83baceb6db7" ## ## ## [[2]] ## [[2]]$number ## [1] 1 ## ## [[2]]$timestamp ## [1] "2022-05-20 09:15:32 CEST" ## ## [[2]]$data ## [1] "I'm block 1" ## ## [[2]]$parent_hash ## [1] "000cd4fd973996089cea1548897b5cc5e94e00cf5f7cd96b6854e83baceb6db7" ## ## [[2]]$nonce ## [1] 343 ## ## [[2]]$hash ## [1] "00038c8e72f307c35c5a885d5671e8877dd9b0d66744c45e38d47d0e0d454741" ## ## ## [[3]] ## [[3]]$number ## [1] 2 ## ## [[3]]$timestamp ## [1] "2022-05-20 09:15:32 CEST" ## ## [[3]]$data ## [1] "I'm block 2" ## ## [[3]]$parent_hash ## [1] "00038c8e72f307c35c5a885d5671e8877dd9b0d66744c45e38d47d0e0d454741" ## ## [[3]]$nonce ## [1] 4353 ## ## [[3]]$hash ## [1] "00063d187474501299b815e3f21db6bbd7b029dd75d17aad4b6afe1151b8c568"
## Digital signature # load library library(openssl) # generate a private key (prikey) and a public key (pubkey) prikey <- rsa_keygen() pubkey <- prikey$pubkey # Write keys in Privacy-Enhanced Mail (PEM) format write_pem(pubkey)
## [1] "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2l3ZYWvtPl/yDOtVaYcr\nnkM6PaejA/XlISLSemVAjl2q7hWhflFYIyPiQa41XC57Q6Mjrdy/jYGaqBagpM4q\nMSmCN3+Q6ysTpHOGce8HuaFewuMvh0lGlrM4Y5drsWdQ9p358zZaf1AsL2xklCER\nJRK9Q20rMlKr1/GyU0hWwZ6NnjG72rW/pFbOQ9rU2R4CXxZYzVq3JVKULTq40I5Q\n3rmIcOij1jkgvnaAD3lbipan9o1EfpddX6PezcZvEFJ//gyjIbslXVUajLAEdBu3\nY8tI5ZquWwRNCnVYA1oIIphSCdDcJTwI8dc3KcjXro+onOXEWc/XN3FbvWfBIF87\nHQIDAQAB\n-----END PUBLIC KEY-----\n"
write_pem(prikey)
## [1] "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDaXdlha+0+X/IM\n61VphyueQzo9p6MD9eUhItJ6ZUCOXaruFaF+UVgjI+JBrjVcLntDoyOt3L+NgZqo\nFqCkzioxKYI3f5DrKxOkc4Zx7we5oV7C4y+HSUaWszhjl2uxZ1D2nfnzNlp/UCwv\nbGSUIRElEr1DbSsyUqvX8bJTSFbBno2eMbvatb+kVs5D2tTZHgJfFljNWrclUpQt\nOrjQjlDeuYhw6KPWOSC+doAPeVuKlqf2jUR+l11fo97Nxm8QUn/+DKMhuyVdVRqM\nsAR0G7djy0jlmq5bBE0KdVgDWggimFIJ0NwlPAjx1zcpyNeuj6ic5cRZz9c3cVu9\nZ8EgXzsdAgMBAAECggEAdyM08r4blihquzm6Q/UHizVKlVDc09BYzpddFoIfkozw\nMS2ECpL+700oqIUPf9esUN61HKqPp/jKFGMkCkahJmlrLjRfMK8z7ElLVOYA5Ppx\n5QpmZ/1Gkfn+DfgTPZsMxUCzmkpRXZy0Prt4tIjF/eAXeq4ZHz+TmiG4FVAmZUPF\nf2nVre7etP0ys2YsO1Y9iJbvjtb6GSyb243cPnMO2X6FZjWiwB/8qg5F4pVd5yFi\n7Obwy41IgqdBiE88xXmm0XnD+n+XdHzQ+EMRF+Hn7kmfIMJpSE6vjZajfIdoisX1\nyTBkfjLiAGjVaMGl0K6RbNwyDcFk7EDj+iNQySEvUQKBgQD+BSgkGbwpxckzki54\nKlmLn3G5A48sHCn3FjiohnQsqZeMYPU6vN+vY6rpaM+2qq8dKtgvAvL5IYPyE5bL\nQkKVJMoXx1YXMvQXw1srlvtI/3f/S8mId8kZvkC6vR3e19iBxSpJOcYGaf6SJMGa\nJQhygR39ri67ML/NqXIA0t62rwKBgQDcEY2jJ1M/hm7ZQ9aT8bw9BYvhIPPjWyGl\nptGNJr0OjYe3d75sH0IKGRsllHQzdmBh04MnnzmZFM0LHavAaOS6dK1bEQ3zlqF3\nQHBb69qj8dE6zmo8LXZtB/G0/jeK9mQNN5NuamuOLWKrXbMyS1KPAbUrNNcwQwWi\n2Q43WZod8wKBgH4M/wtS/e1YqWv+6TJWCZNgbqVZn81KuIRVMY5nEfUrvvk5D9ey\n6+jzs1cZ3KEPd9Aod5h0hS+dMwWINPbuDW5HEEXWc+EVNs0n8vDhfhaONvSnnf0r\nO86bezFvMQho4ZYbyc0Gbz61kE7jEHM2V0fCzKgarDPVkAg1Qk4oVb4fAoGAD5nW\n9qgFCM3Y8eITRi2u8IyCHBWf9JAzVHD9DgqfAHccFe+ROk0E+35IJGPf0P4lWwoJ\nlDd/d9C3sIAL+vn0rRs0Zu5QlOIq1C9nR7zypQixkn+rnFSEvrn/cptLCLjq4tz7\nwKoesdeZ1RgxafFZCvZOB6AZWTyHG8JTda0Ode0CgYAhCuo2oyWclj6IKm2p0+d6\nLFyfGVcvxEY4Jyky7Ud2AqA+a12ep6dWKFtLyRN1pIUlMcI7zuc+fLYAsphgNb1M\n6mc26tfVduqqjsw1DCyiQqhG/Oe6AClc29ybgPmTAI+ezzt3VkRIGMciI1gXcBio\n231wuSOMXzazYZ5sAVcoJw==\n-----END PRIVATE KEY-----\n"
# build a transaction trans = list(sender = "A", receiver = "B", amount = "100") # serialize data data <- serialize(trans, NULL) # sign (a hash of) the transaction with private key sig <- signature_create(data, sha256, key = prikey) # verify the message with public key signature_verify(data, sig, sha256, pubkey = pubkey)
## [1] TRUE
## Encryption # load library library(openssl) # generate a private key (prikey) and a public key (pubkey) prikey <- rsa_keygen(512) pubkey <- prikey$pubkey # message msg <- charToRaw("HODL!") # cipher the message with public key ciphermsg <- rsa_encrypt(msg, pubkey) # decrypt the message with private key rawToChar(rsa_decrypt(ciphermsg, prikey))
## [1] "HODL!"
Finally, the blockchain ledger is distributed over a peer-to-peer network.
The steps to run the network are as follows:
The incentive of rewards may help encourage nodes to stay honest.
If a greedy attacker is able to assemble more CPU power than all the honest nodes, he would have to choose between using it to defraud people by stealing back his payments, or using it to generate new coins.
He ought to find it more profitable to play by the rules (generate new coins), such rules that favor him with more new coins than everyone else combined, than to undermine the system and the validity of his own wealth. Satoshi Nakamoto (Bitcoin white paper)