Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

How to Build the Simplest Blockchain With Ruby

DZone's Guide to

How to Build the Simplest Blockchain With Ruby

Want to learn how to install your own blockchain? Check out this post on how to build a simple blockchain using the Ruby web server framework!

· Security Zone ·
Free Resource

Mobile is increasingly becoming a part of every consumers’ identity, but the increasing use of this digital channel is escalating the security risks faced by consumers and institutions.

Blockchain is a revolutionary technology that is starting to have a significant impact on businesses worldwide. Despite its abstractness and complexity, blockchain brings various benefits to industries, such as greater transparency and enhanced security.

However, it takes time to study the design and master specific programming languages for blockchain. Appropriate learning materials help shorten this process, which is why, since the emergence of Bitcoin, a barrage of popular online content has been released to explain how it works.

In October 2017, Mr. Haseeb Qureshi, a well-known blockchainist, posted a blockchain demo and source code for making a simple blockchain using Ruby. In my opinion, this is one of the best materials available online to help the public better understand blockchain. In this article, we'll be taking a closer look at Mr. Qureshi's demo. Specifically, we will be talking about the six stages involved in making a functional blockchain with Ruby.

1

Stage 1: Money Transfer

Balance check and money transfer are implemented at this stage. The transfer is addition or subtraction performed based on the account balance.

GET and POST of the HTTP protocol are the most suitable options to implement this functionality. GET obtains data from the server, and POST changes data on the server.

Here, the presentation of the UI does not require an HTML protocol. You can use the Ruby web framework Sinatra to organize URLs and related methods to view the transfer information in the command line by using UE.

Methods on the client and URLs on the server are quite simple:

Client: client.rb

def create_user(name) … end

  def get_balance(user)  … end

  def transfer(from, to, amount) ... end


Server: haseebcoin.rb

get "/balance" ... end

  post "/users" ... end

  post "/transfers" ... end


Required knowledge for this layer includes: Ruby, HTTP GET, POST, and the Sinatra framework.

Stage 2: Building a Gossip Network

The blockchain has a decentralized structure, known as "Gossip Protocol." The word "gossip" here is not referring rumors but information that gets disseminated in a decentralized network.

Let's build a Gossip network where movie names can get exchanged.

client.rb sends messages to a specified port:

def self.gossip(port, state)
  ...  

  Faraday.post("#{URL}:#{port}/gossip", state: state).body

  ...

end


 gossip.rb  receives two parameters: the source port and the destination port. They exchange information through specific ports on the source end, such as ports 1111 and 2222.

In a real decentralized network, the two ports are essentially two network nodes. Exchanging information between different local ports represents the communication between different nodes in a simulated network.

On each node, you will be able to express your favorite movie name every 3 seconds:

every(3.seconds) do

  …

  gossip_response = Client.gossip(port, JSON.dump(STATE))

  update_state(JSON.load(gossip_response))

  ...

end


Now, you can change the favorite movie name every 8 seconds:

every(8.seconds) do

  …

  update_state(PORT => [@favorite_movie, @version_number])

  ...

end


The server receives and processes the data:

post '/gossip' do

  …

  update_state(JSON.load(their_state))

  …

end


In a four-person network:

  1. Run gossip.rb   1111 at the initial node. The first node speaks out a favorite movie name at port 1111.
  2. Run gossip.rb   2222 1111. The second node speaks a favorite movie name at port 2222 to the first node (port 1111).
  3. Run gossip.rb  3333 2222. The third node speaks a favorite movie name at port 3333 to the second node (port 2222).
  4. Run gossip.rb  4444 3333. The fourth node speaks a favorite movie name at port 4444 to the third node (port 3333).

After running for a period, the four nodes finally obtain information of peer ends, and the data keeps changing. This is a simple Gossip network.

Stage 3: Data Encryption and Decryption

Top-level encryption algorithms are the foundation of blockchain. The asymmetric encryption technology is used at this layer to implement blockchain accounts. The RSA algorithm can generate public keys, private keys, and enforce asymmetric encryption.

def generate_key_pair … end
def sign(plaintext, raw_private_key) ... end


Thanks to the OpenSSL module in the Ruby language, we can quickly implement asymmetric encryption and signature verification. In blockchain, public keys are accounts, and private keys are passwords. Each pair of keys is one blockchain account.

Decrypt the ciphertext:

def plaintext(ciphertext, raw_public_key) … end


Verify whether the ciphertext is a message:

def valid_signature?(message, ciphertext, public_key) … end


Required knowledge for this layer: asymmetric encryption algorithm

Stage 4: Data Mining

At this stage, proof-of-work gets implemented, and blocks get generated for the blockchain. It is a time-consuming and arduous process. Hash functions are irreversible and free of conflicts. The calculation process is straightforward. A result is obtained by merely performing a hash operation on the input.

The input is the information about money transfer, including the transfer amount, the remitter's name, the recipient's name, and so on. Hash operations have various algorithms.

Here, the SHA256 algorithm gets used:

def hash(message) … end


When the same information gets hashed, different results come up each time. We keep performing operations until the obtained result meets some features, for example, starting with several digits of 0.

Verify whether the result starts with several digits of 0:

def is_valid_nonce?(nonce, message)

  hash(message + nonce).start_with?("0" * NUM_ZEROES)

end


It is not easy to perform operations to meet the above conditions. They consume a lot of time. The entire process is called mining:

def find_nonce(message)

  …  

  until is_valid_nonce?(nonce, message)

  ...

end


The input includes the result of the previous hash operation. Therefore, each hash operation gets affected by the previous one. In other words, this is a chain structure. That is why it is called blockchain.

Stage 5: The Longest Chain Rule

At this stage, the first block gets initialized and, accordingly, a chain structure gets generated to form a blockchain. Blockchain can get stored in the array structure. During storage, the blocks must get validated.

Initialize the block: class Block

def initialize(prev_block, msg)

  @msg = msg

  @prev_block_hash = prev_block.own_hash if prev_block

  mine_block!

end


The most challenging work during mining is finding a nonce.

def mine_block!

  @nonce = calc_nonce

  @own_hash = hash(full_block(@nonce))

end


A complete block gets compacted in this way:

def full_block(nonce)

  [@msg, @prev_block_hash, nonce].compact.join

end


Initialize the blockchain: class BlockChain — merely use array to store it!

def initialize(msg)

  @blocks = []

  @blocks << Block.new(nil, msg)

end


Now, add blocks to the chain. The entire blockchain is continuously growing:

def add_to_chain(msg)

  @blocks << Block.new(@blocks.last, msg)

  puts @blocks.last

end


You must validate rigorously whether the blocks are healthy:

def valid?

  @blocks.all? { |block| block.is_a?(Block) } &&

    @blocks.all?(&:valid?) &&

    @blocks.each_cons(2).all? { |a, b| a.own_hash == b.prev_block_hash }

end


Stage 6: Combining the Pieces

Finally, blockchain works its magic through a harmonious collaboration with every component in the network. At stage one, the transfer is of the Transaction  class and needs to use a private key to sign the information.

@signature = PKI.sign(message, priv_key)


The reward for the miner gets the first block is 500,000 pieces of silver.

def self.create_genesis_block(pub_key, priv_key)

  genesis_txn = Transaction.new(nil, pub_key, 500_000, priv_key)

  Block.new(nil, genesis_txn)

end


Now, verify whether spending charged to the account is valid.

def all_spends_valid?

  compute_balances do |balances, from, to|

    return false if balances.values_at(from, to).any? { |bal| bal < 0 }

  end

  true

end


Next, add unknown node $PEERS to maintain the growth of the network.

if PEER_PORT.nil?

  # You are the progenitor!

  $BLOCKCHAIN = BlockChain.new(PUB_KEY, PRIV_KEY)

  else

  # You're just joining the network.

  $PEERS << PEER_PORT

end


Data processing between nodes reads and, then, updates the blockchain and peers.

# @param blockchain

# @param peers

post '/gossip' do

  their_blockchain = YAML.load(params['blockchain'])

  their_peers = YAML.load(params['peers'])

  update_blockchain(their_blockchain)

  update_peers(their_peers)  

  YAML.dump('peers' => $PEERS, 'blockchain' => $BLOCKCHAIN)

end


Processing a received block focuses on whether the chain is getting longer:

def update_blockchain(their_blockchain)  

  return if their_blockchain.nil?

  return if $BLOCKCHAIN && their_blockchain.length <= $BLOCKCHAIN.length

  return unless their_blockchain.valid?  $BLOCKCHAIN = their_blockchain

  end


Update peers so far as they are new.

def update_peers(their_peers)

  $PEERS = ($PEERS + their_peers).uniq

end


When transferring money, get the recipient's pub_key   and then transfer the funds through the remitter's  pub_key.

# @param to (port_number)

# @param amount

post '/send_money' do

  to = Client.get_pub_key(params['to'])

  amount = params['amount'].to_i

  $BLOCKCHAIN.add_to_chain(Transaction.new(PUB_KEY, to, amount, PRIV_KEY))

  'OK. Block mined!'


end


Lastly, put the blockchain into a Gossip network and assemble all functional components. There you go! You have successfully created a working blockchain!

You can find more information about this demo on Github.

Explore the authentication advancements that are designed to secure accounts and payments—without overburdening consumers with a friction-laden experience.

Topics:
ruby ,blockchain ,security ,tutorial ,post ,gossip network

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}