Blockchains are decentralized, distributed ledger systems that enable secure and transparent record-keeping of transactions. They are made up of a chain of blocks, each containing a list of transactions and a cryptographic hash of the previous block. This design makes it extremely difficult to alter the contents of a block once it has been added to the chain, as doing so would require changing all subsequent blocks as well.

In this tutorial, we will learn how to create a basic blockchain in Ruby. We will start by understanding the fundamentals of blockchains and how they work. Then, we will implement a class for the blockchain and define functions for adding blocks and transactions to the chain. Finally, we will implement a mechanism for finding the proof of work for a new block and validating the proof.

First, let’s create a new Ruby file and define the `Blockchain`

class:

```
# Define a class for a blockchain
class Blockchain
attr_reader :chain, :current_transactions
def initialize
# Create an array to store the chain of blocks
@chain = []
# Create an array to store the current list of transactions
@current_transactions = []
# Create the first block in the chain (the "genesis block")
create_block(previous_hash: 1, proof: 100)
end
end
```

The `Blockchain`

class has two instance variables: `@chain`

, which is an array that stores the chain of blocks, and `@current_transactions`

, which is an array that stores the current list of transactions. The `initialize`

method creates these instance variables and creates the first block in the chain, known as the “genesis block”.

Next, let’s define a function to create a new block in the chain:

```
# Define a function to create a new block in the chain
def create_block(proof:, previous_hash:)
# Create a new block and add it to the chain
block = {
index: @chain.length + 1,
timestamp: Time.now,
transactions: @current_transactions,
proof: proof,
previous_hash: previous_hash,
}
# Reset the current list of transactions
@current_transactions = []
# Add the new block to the chain
@chain << block
# Return the new block
block
end
```

This function creates a new block using a hash that contains the following information:

`index`

: the position of the block in the chain`timestamp`

: the time at which the block was created`transactions`

: the list of transactions contained in the block`proof`

: the proof of work for the block (more on this later)`previous_hash`

: the cryptographic hash of the previous block in the chain

Once the block has been created, the function resets the current list of transactions and adds the new block to the end of the chain. It then returns the new block.

Now that we have a way to create new blocks, let’s define a function to add new transactions to the list of current transactions:

```
# Define a function to add a new transaction to the list of current transactions
def add_transaction(sender:, recipient:, amount:)
# Add a new transaction to the list of current transactions
@current_transactions << {
sender: sender,
recipient: recipient,
amount: amount,
}
# Return the index of the block that the transaction will be added to
@chain.length + 1
end
```

This function adds a new transaction to the list of current transactions using a hash that contains the following information:

`sender`

: the address of the sender`recipient`

: the address of the recipient`amount`

: the amount of coins being transferred

It then returns the index of the block that the transaction will be added to.

Here is the rest of the `proof_of_work`

function:

```
# Define a function to find the proof of work for a new block
def proof_of_work(last_proof)
# Set the initial proof to 0
proof = 0
# Keep incrementing the proof until it is valid
while valid_proof?(last_proof, proof) do
proof += 1
end
# Return the proof
proof
end
```

This function starts with an initial proof of 0 and increments it until it becomes a valid proof. The `valid_proof?`

function, which we will define next, checks if the proof is valid.

Finally, let’s define the `valid_proof?`

function:

```
# Define a function to validate the proof of work for a new block
def valid_proof?(last_proof, proof)
# Calculate the hash of the proof
guess = "#{last_proof}#{proof}"
guess_hash = Digest::SHA256.hexdigest(guess)
# Check if the hash starts with four leading zeros
guess_hash[0..3] == "0000"
end
```

This function calculates the hash of the proof using the Ruby `Digest`

module and checks if the hash starts with four leading zeros. If it does, the proof is considered valid. Otherwise, the `proof_of_work`

function will continue to increment the proof until it becomes valid.

In the `valid_proof?`

function, the hash of the proof is compared with four leading zeros because this is a common way to verify that a proof of work is valid. A proof of work is a mathematical problem that is designed to be computationally difficult to solve, but easy to verify. It is used to secure a blockchain by requiring users to perform a certain amount of work in order to add new blocks to the chain.

The concept that this comparison represents is known as the “difficulty” of the proof of work. The more leading zeros that are required, the more difficult the proof of work becomes. In the example code, we are using a difficulty of four leading zeros, which means that the proof must be a number that, when hashed, produces a hash that starts with four zeros. This can take some time to find, as the proof must be incremented until a valid hash is found.

The use of proof of work helps to prevent fraud and ensure the integrity of the blockchain. It ensures that new blocks cannot be added to the chain without performing the necessary work, and it makes it difficult for an attacker to alter the contents of a block once it has been added to the chain.

Now that we have implemented all the necessary functions for our blockchain, let’s try it out. Create a new instance of the `Blockchain`

class and add some transactions to it:

```
# Create a new blockchain
blockchain = Blockchain.new
# Add some transactions to the blockchain
blockchain.add_transaction(sender: "Alice", recipient: "Bob", amount: 10)
blockchain.add_transaction(sender: "Bob", recipient: "Charlie", amount: 5)
# Create a new block
blockchain.create_block(proof: 123, previous_hash: 1)
# Add some more transactions to the blockchain
blockchain.add_transaction(sender: "Charlie", recipient: "Alice", amount: 3)
blockchain.add_transaction(sender: "Alice", recipient: "Bob", amount: 7)
# Create another new block
blockchain.create_block(proof: 456, previous_hash: 123)
# Print the blockchain
puts blockchain.chain
```

This code creates a new blockchain, adds some transactions to it, creates two new blocks, and prints the final chain. The output should look something like this:

`[{:index=>1, :timestamp=>2022-12-19 13:43:01 -0800, :transactions=>[], :proof=>100, :previous_hash=>1}, {:index=>2, :timestamp=>2022-12-19 13:43:01 -0800, :transactions=>[{:sender=>"Alice", :recipient=>"Bob", :amount=>10}, {:sender=>"Bob", :recipient=>"Charlie", :amount=>5}], :proof=>123, :previous_hash=>1}, {:index=>3, :timestamp=>2022-12-19 13:43:01 -0800, :transactions=>[{:sender=>"Charlie", :recipient=>"Alice", :amount=>3}, {:sender=>"Alice", :recipient=>"Bob", :amount=>7}], :proof=>456, :previous_hash=>123}]`

This is the final state of the blockchain, with three blocks containing the transactions that we added. You can see that each block contains the list of transactions, the proof of work, and the hash of the previous block.

Congratulations, you have successfully implemented a basic blockchain in Ruby! In the next tutorial, we will learn how to enhance this blockchain with advanced features such as a decentralized network of nodes, consensus algorithms, and cryptography.

I hope this tutorial has been helpful and that you have a better understanding of how blockchains work and how to implement them in Ruby.