Simple Blockchain Example in R

This R markdown post was inspired by the R-bloggers post Building your own blockchain in R.

Blockchain technology, types such as bitcoin and ethereum and its associated terminology are ubiquitous in the media at the moment.

The objective here is to learn how a generic blockchain works and understand some of the terminology through implementing a simple example. This generic example could then extended to various types of blockchains such as distributed ledgers, smart contracts or cryptocurrencies with network servers and appropriate privacy and security settings.

This post and it’s visuals has also been a useful reference.


Setup

LOAD R PACKAGES

library(tidyverse) # imports all tidyverse packages incuding dplyr, ggplot2
## Warning: package 'tidyverse' was built under R version 3.5.1
## Warning: package 'ggplot2' was built under R version 3.5.1
library(digest) # Create hash function digests for R objects

Background

Wikipedia defines a blockchain as:

a continuously growing list of records, called blocks, which are linked and secured using cryptography. Each block typically contains a hash pointer as a link to a previous block, a timestamp and transaction data.

a decentralized and distributed digital ledger that is used to record transactions across many computers so that the record cannot be altered retroactively without the alteration of all subsequent blocks and the collusion of the network.

Every node or miner in a decentralized system has a copy of the blockchain. Data quality is maintained by massive database replication and computational trust. No centralized “official” copy exists and no user is “trusted” more than any other.

Defining a Blockchain Structure

1. BLOCK

Each block is created by consensus in the network and contains the following:

  • Index
  • Timestamp
  • Transactions
  • Consensus system
  • Hash of the previous block
  • Hash of the current block

2. HASH

Each block in the blockchain needs to be “hashed” or chained to keep the integrity of the data in the block. The digest R package has the digest function which applies a cryptographical hash function to arbitrary R objects using algorithms.

3. TRANSACTIONS

Transactions are block data such as ledger facts, assets, conditions or executable programs.

4. CONSENSUS SYSTEM

A consensus system of algorithms seeks to guarantee integrity of the chain for the nodes to agree on the ordering of the blocks.

In crypocurrencies proofs such as “mining” algorithms Proof of Stake (PoS) or Proof of Work (PoW) determine the consensus.

5. NODES

Nodes are members of the distributed network are anonymous individuals, typically a computer in the network.

At any time the blockchain is a single chain of blocks, with a copy read and held by each node.

In cryptocurrencies, nodes can also add blocks for a fee, or be the miners that look for blocks and recuperate the fees from that block.

In this example there is a single node and no fees.

Create a blockchain

Initially, we need to create an empty blockchain with the following:

  • a list of blocks (the chain)
  • a list of nodes.

Lists are useful R objects as they

model objects that are like trees. You can create a hierarchical structure with a list because unlike vectors, a list can contain other lists.

# Create the empty blockchain as embedded lists
blockchain <- list(
    chain = list(),
    nodes = list()
  )
# Review the blockchain 
str(blockchain)
## List of 2
##  $ chain: list()
##  $ nodes: list()

Add the node name to the blockchain.

# Add the node name
blockchain$nodes <- "Betty's PC"
# Review the blockchain so far
str(blockchain)
## List of 2
##  $ chain: list()
##  $ nodes: chr "Betty's PC"

Next we will create a function that creates a new block calculating the hash with the digest function from the digest R package. The first block is called the Genesis block.

# Create a new block in the Blockchain function
nextBlock <- function (previousHash, transactions){
  thisHash <- digest((length (blockchain$chain) + 1),algo="sha256")
  block <- list('block' = list('index' = length (blockchain$chain), 
                                'timestamp' = Sys.time() , 
                                'transactions' =  transactions,
                                'thisHash' = thisHash, 
                                'previousHash' = previousHash))
    blockchain$chain <- c(blockchain$chain, block)
}
# Create the first block, the Genesis block, setting previous hash to 0  and thisHash to the calculated hashBlock
blockchain$chain$block<- nextBlock(previousHash=0, transactions="Genesis block") 
# Review the blockchain so far, with block 1
str(blockchain)
## List of 2
##  $ chain:List of 1
##   ..$ block:List of 1
##   .. ..$ block:List of 5
##   .. .. ..$ index       : int 0
##   .. .. ..$ timestamp   : POSIXct[1:1], format: "2018-08-15 16:43:53"
##   .. .. ..$ transactions: chr "Genesis block"
##   .. .. ..$ thisHash    : chr "744e41f7d7e1f05bd29229a944ee598b94d593aec4c012e50bdeb63a1cd0b6b7"
##   .. .. ..$ previousHash: num 0
##  $ nodes: chr "Betty's PC"

Now create the second block reusing the existing function, nextBlock.

# Create the next block, setting this block's hash to hashBlock and prevhashBlock to the Genesis block's hash
prevhashBlock <- blockchain$chain$block[1]$block$thisHash
blockchain$chain$block <- nextBlock(previousHash=prevhashBlock,transactions="FACT ABC") 
# Review the blockchain so far
str(blockchain)
## List of 2
##  $ chain:List of 1
##   ..$ block:List of 2
##   .. ..$ block:List of 1
##   .. .. ..$ block:List of 5
##   .. .. .. ..$ index       : int 0
##   .. .. .. ..$ timestamp   : POSIXct[1:1], format: "2018-08-15 16:43:53"
##   .. .. .. ..$ transactions: chr "Genesis block"
##   .. .. .. ..$ thisHash    : chr "744e41f7d7e1f05bd29229a944ee598b94d593aec4c012e50bdeb63a1cd0b6b7"
##   .. .. .. ..$ previousHash: num 0
##   .. ..$ block:List of 5
##   .. .. ..$ index       : int 1
##   .. .. ..$ timestamp   : POSIXct[1:1], format: "2018-08-15 16:43:54"
##   .. .. ..$ transactions: chr "FACT ABC"
##   .. .. ..$ thisHash    : chr "1a90a573c200ff39ac0012de2dc7cfa29300068ecc958bb7149645bb593da909"
##   .. .. ..$ previousHash: chr "744e41f7d7e1f05bd29229a944ee598b94d593aec4c012e50bdeb63a1cd0b6b7"
##  $ nodes: chr "Betty's PC"