Simple Blockchain with R
Understanding Blockchains by Coding One in R:This article uses a proof-of-work algorithm other than the BTC’s that helps understand the design and evaluation of the algorithm’s ideas.
Building your own blockchain in R:This article is very detailed and creates an local interactive API.
-
Each block in the blockchain is represented by a
listin R, containing the content that needs to be stored. -
New blocks are created by taking the hash value of the previous block’s content to ensure that the previous block’s content cannot be modified, and it is currently impossible to infer the content represented by the hash value by exhaustive search.
-
Introduce a proof-of-work algorithm to increase the difficulty of creating a block, i.e. adding additional verification to each block to determine whether the new block is valid.
Creating the First Block
The data type list can store multiple different types of data in one object.
In addition to the data to be stored, a block also includes time, block index, the previous block’s hash, and a counter for proof-of-work verification.
1# Create a list to store our blockchain
2blockchain <- list()
3
4# Create the first block in the blockchain
5blockchain[[1]] <- list(index = 1,
6 timestamp = Sys.time(),
7 data = "Genesis Block",
8 previous_hash = "0",
9 nonce = 0)
Hashing a Single Block
Use the digest function to calculate the hash of a block.
1# Function to calculate the hash of a block
2hash_block <- function(block) {
3 return(digest::digest(toString(block)))
4}
“Mining” Function
“Mining” is the verification of creating a new block through the proof-of-work algorithm. BTC’s verification is that the hash of the new block meets the requirement of having a consecutive $n$ number of 0s at the beginning. $n$ is adjusted by the number of actual new blocks created in the past 2 weeks, with the goal of creating a new block every 10 minutes on average.
As of October 2022 (block #760,446), the Bitcoin network required that the first 77 out of 256 hash bits must be zero.
#760,446 ’s hash is 00000000000000000004ee4fcb027dce239c91568cbbc367790a26c06d5b5e2c
A counter called nonce is included in a single block. By repeatedly trying different values for the nonce, a block’s hash is made to satisfy the verification.
Using $n=4$ as an example, the input parameters of the function are the current blockchain and the data to be stored in the new block, and the output is a blockchain with an added block.
1# Function to mine a new block
2mine_block <- function(blockchain, data) {
3 # Get the last block in the blockchain
4 last_block <- blockchain[[length(blockchain)]]
5
6 # Create a new block
7 new_block <- list(index = last_block$index + 1,
8 timestamp = Sys.time(),
9 data = data,
10 previous_hash = hash_block(last_block),
11 nonce = 0)
12
13 # Find a nonce that satisfies the proof-of-work requirement
14 while(substr(hash_block(new_block), 1, 4) != "0000") {
15 new_block$nonce <- new_block$nonce + 1
16 }
17
18 # Add the new block to the blockchain
19 blockchain[[new_block$index]] <- new_block
20
21 return(blockchain)
22}
Example
The following is an example of adding a new block and storing custom data in the blockchain.
1# Add some data to our blockchain
2blockchain <- mine_block(blockchain, "Block 1 Data")
3blockchain <- mine_block(blockchain, "Block 2 Data")
4blockchain <- mine_block(blockchain, "Block 3 Data")
5
6# View the blockchain
7blockchain