Build Your Own Blockchain in 20 Lines of Ruby - blockchain.rb @ Awesome Blockchains

Hello,

   Inspired by Let’s Build the Tiniest Blockchain In Less Than 50
Lines of Python [1] I’ve put together a Ruby version.

   Blockchains, blockchains, blockchains! See the blockchain.rb [2] sample
  in the Awesome Blockchains repo and repasted below.

    Use

    $ ruby ./blockscript.rb to run.

    If you have seen other blockchains in ruby, let us know. Or if you
have ideas how to make it better, let us know. Happy blockchaining.
Let's revolutionize the world with blockchains!

     Cheers.

[1] https://medium.com/crypto-currently/lets-build-the-tiniest-blockchain-e70965a248b
[2] https://github.com/planetopendata/awesome-blockchains/blob/master/blockchain.rb

PS: blockchain.rb:

require "digest" # for hash checksum digest function SHA256
require "pp" # for pp => pretty printer

class Block

  attr_reader :index
  attr_reader :timestamp
  attr_reader :data
  attr_reader :previous_hash
  attr_reader :hash

  def initialize(index, timestamp, data, previous_hash)
    @index = index
    @timestamp = timestamp
    @data = data
    @previous_hash = previous_hash
    @hash = calc_hash
  end

  def self.first( data="Genesis" ) # create genesis (big bang! first) block
    ## uses index zero and arbitrary previous_hash
    Block.new( 0, Time.now, data, "0" )
  end

  def self.next( previous, data="Transaction Data..." )
    Block.new( previous.index+1, Time.now, data, previous.hash )
  end

private

  def calc_hash
    sha = Digest::SHA256.new
    sha.update @index.to_s + @timestamp.to_s + @data.to_s + previous_hash.to_s
    sha.hexdigest
  end

end # class Block

···

#####
## let's get started
## build a blockchain a block at a time

b0 = Block.first( "Genesis" )
b1 = Block.next( b0, "Transaction Data..." )
b2 = Block.next( b1, "Transaction Data......" )
b3 = Block.next( b2, "More Transaction Data..." )

blockchain = [b0, b1, b2, b3]

pp blockchain

######
# will pretty print (pp) something like:
#
# [#<Block:0x1eed2a0
# @data="Genesis",
# @hash="edbd4e11e69bc399a9ccd8faaea44fb27410fe8e3023bb9462450a0a9c4caa1b",
# @index=0,
# @previous_hash="0",
# @timestamp=2017-09-15 20:52:38 +0200>,
# #<Block:0x1eec9a0
# @data="Transaction Data...",
# @hash="eb8ecbf6d5870763ae246e37539d82e37052cb32f88bb8c59971f9978e437743",
# @index=1,
# @previous_hash="edbd4e11e69bc399a9ccd8faaea44fb27410fe8e3023bb9462450a0a9c4caa1b",
# @timestamp=2017-09-15 20:52:38 +0200>,
# #<Block:0x1eec838
# @data="Transaction Data......",
# @hash="be50017ee4bbcb33844b3dc2b7c4e476d46569b5df5762d14ceba9355f0a85f4",
# @index=2,
# @previous_hash="eb8ecbf6d5870763ae246e37539d82e37052cb32f88bb8c59971f9978e437743",
# @timestamp=2017-09-15 20:52:38 +0200>,
# #<Block:0x1eec6d0
# @data="More Transaction Data...",
# @hash="5ee2981606328abfe0c3b1171440f0df746c1e1f8b3b56c351727f7da7ae5d8d",
# @index=3,
# @previous_hash="be50017ee4bbcb33844b3dc2b7c4e476d46569b5df5762d14ceba9355f0a85f4",
# @timestamp=2017-09-15 20:52:38 +0200>]

Hello, I am excited by this and will definitely try the code to see if it leads me to understand blockchain. However I started reading the python blogpost and noted,

“each block’s hash will be a cryptographic hash of the block’s index, timestamp, data, and the hash of the previous block’s hash.”

I work with all sorts of networked computers, reading logs. Very often a log that grows by appending will be found with non sequential timestamps from a variety of hardware or software reasons. This can affect logs from production servers to end user computers. How would this affect blockchain and would it matter?

David.

···

Sent from my Windows 10 phone

From: Gerald Bauer<mailto:gerald.bauer@gmail.com>
Sent: 15 September 2017 20:52
To: Ruby users<mailto:ruby-talk@ruby-lang.org>
Subject: Build Your Own Blockchain in 20 Lines of Ruby - blockchain.rb @ Awesome Blockchains

Hello,

   Inspired by Let’s Build the Tiniest Blockchain In Less Than 50
Lines of Python [1] I’ve put together a Ruby version.

   Blockchains, blockchains, blockchains! See the blockchain.rb [2] sample
  in the Awesome Blockchains repo and repasted below.

    Use

    $ ruby ./blockscript.rb to run.

    If you have seen other blockchains in ruby, let us know. Or if you
have ideas how to make it better, let us know. Happy blockchaining.
Let's revolutionize the world with blockchains!

     Cheers.

[1] https://medium.com/crypto-currently/lets-build-the-tiniest-blockchain-e70965a248b
[2] https://github.com/planetopendata/awesome-blockchains/blob/master/blockchain.rb

PS: blockchain.rb:

require "digest" # for hash checksum digest function SHA256
require "pp" # for pp => pretty printer

class Block

  attr_reader :index
  attr_reader :timestamp
  attr_reader :data
  attr_reader :previous_hash
  attr_reader :hash

  def initialize(index, timestamp, data, previous_hash)
    @index = index
    @timestamp = timestamp
    @data = data
    @previous_hash = previous_hash
    @hash = calc_hash
  end

  def self.first( data="Genesis" ) # create genesis (big bang! first) block
    ## uses index zero and arbitrary previous_hash
    Block.new( 0, Time.now, data, "0" )
  end

  def self.next( previous, data="Transaction Data..." )
    Block.new( previous.index+1, Time.now, data, previous.hash )
  end

private

  def calc_hash
    sha = Digest::SHA256.new
    sha.update @index.to_s + @timestamp.to_s + @data.to_s + previous_hash.to_s
    sha.hexdigest
  end

end # class Block

#####
## let's get started
## build a blockchain a block at a time

b0 = Block.first( "Genesis" )
b1 = Block.next( b0, "Transaction Data..." )
b2 = Block.next( b1, "Transaction Data......" )
b3 = Block.next( b2, "More Transaction Data..." )

blockchain = [b0, b1, b2, b3]

pp blockchain

######
# will pretty print (pp) something like:
#
# [#<Block:0x1eed2a0
# @data="Genesis",
# @hash="edbd4e11e69bc399a9ccd8faaea44fb27410fe8e3023bb9462450a0a9c4caa1b",
# @index=0,
# @previous_hash="0",
# @timestamp=2017-09-15 20:52:38 +0200>,
# #<Block:0x1eec9a0
# @data="Transaction Data...",
# @hash="eb8ecbf6d5870763ae246e37539d82e37052cb32f88bb8c59971f9978e437743",
# @index=1,
# @previous_hash="edbd4e11e69bc399a9ccd8faaea44fb27410fe8e3023bb9462450a0a9c4caa1b",
# @timestamp=2017-09-15 20:52:38 +0200>,
# #<Block:0x1eec838
# @data="Transaction Data......",
# @hash="be50017ee4bbcb33844b3dc2b7c4e476d46569b5df5762d14ceba9355f0a85f4",
# @index=2,
# @previous_hash="eb8ecbf6d5870763ae246e37539d82e37052cb32f88bb8c59971f9978e437743",
# @timestamp=2017-09-15 20:52:38 +0200>,
# #<Block:0x1eec6d0
# @data="More Transaction Data...",
# @hash="5ee2981606328abfe0c3b1171440f0df746c1e1f8b3b56c351727f7da7ae5d8d",
# @index=3,
# @previous_hash="be50017ee4bbcb33844b3dc2b7c4e476d46569b5df5762d14ceba9355f0a85f4",
# @timestamp=2017-09-15 20:52:38 +0200>]

Hello,

Very often a log that grows by appending will be found with non sequential timestamps
from a variety of hardware or software reasons. This can affect logs from production
servers to end user computers. How would this affect blockchain and would it matter?

  You bundle your transactions - the "payload" data into blocks and
the block has its own timestamp e.g.

class Block

  attr_reader :index
  attr_reader :timestamp
  attr_reader :data
  attr_reader :previous_hash
  attr_reader :hash

  def initialize(index, timestamp, data, previous_hash)
    @index = index
    @timestamp = timestamp
    @data = data
    @previous_hash = previous_hash
    @hash = calc_hash
  end

   def self.next( previous, data="Transaction Data..." )
    Block.new( previous.index+1, Time.now, data, previous.hash )
  end

   ...

    A blockchain gets build (appended) one block at a time without any
forks or branches - it's a simple chain (linked list or array).

    Thus, before you append / add a block check if the timestamp is in
order / older - if yes, append - if not throw an exception / raise an
error (and do NOT append).

      No magic. With a blockchain all laws of thermodynamics and
gravity still apply ,-) Cheers.

I don't really think it's as easy as that. It would make a lot of sense to
have a Lamport clock instead of an usual timestamp, because it's quite
common in distributed systems.

Second, even though, your program works for a very broad definition of
blockchain, it is not really usable as is. There is no proof-of-work, so
anybody could rewrite the whole blockchain in a matter of microseconds. The
proof-of-work algorithm is probably the most important piece of the
algorithm.

Good luck with this project. :slight_smile:

···

On Sun, Sep 17, 2017, 6:14 PM Gerald Bauer <gerald.bauer@gmail.com> wrote:

Hello,

> Very often a log that grows by appending will be found with non
sequential timestamps
> from a variety of hardware or software reasons. This can affect logs
from production
> servers to end user computers. How would this affect blockchain and
would it matter?

  You bundle your transactions - the "payload" data into blocks and
the block has its own timestamp e.g.

class Block

  attr_reader :index
  attr_reader :timestamp
  attr_reader :data
  attr_reader :previous_hash
  attr_reader :hash

  def initialize(index, timestamp, data, previous_hash)
    @index = index
    @timestamp = timestamp
    @data = data
    @previous_hash = previous_hash
    @hash = calc_hash
  end

   def self.next( previous, data="Transaction Data..." )
    Block.new( previous.index+1, Time.now, data, previous.hash )
  end

   ...

    A blockchain gets build (appended) one block at a time without any
forks or branches - it's a simple chain (linked list or array).

    Thus, before you append / add a block check if the timestamp is in
order / older - if yes, append - if not throw an exception / raise an
error (and do NOT append).

      No magic. With a blockchain all laws of thermodynamics and
gravity still apply ,-) Cheers.

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

--

FR +33 9 77 19 99 93

US +1 678 901-9816

HK +852 5687 5995