How do I convert to Crystal ruby s multiple assignments of Array

0 votes

I have a small (formerly) ruby blockchain script I'm trying to convert over into Crystal, that looks like this so far:

#  build your own blockchain from scratch in crystal!
#
#  to run use:
#    $ crystal ./blockchain_with_proof_of_work.cr

require "openssl" # for hash checksum digest function SHA256

class Block
  getter index : Int32
  getter timestamp : Time
  getter data : String
  getter previous_hash : String
  getter nonce : Int32 # # proof of work if hash starts with leading zeros (00)
  getter hash : String

  def initialize(index, data, previous_hash)
    @index = index
    @timestamp = Time.now
    @data = data
    @previous_hash = previous_hash
    @nonce, @hash = compute_hash_with_proof_of_work
  end

  def compute_hash_with_proof_of_work(difficulty = "00")
    nonce = 0
    loop do
      hash = calc_hash_with_nonce(nonce)
      if hash.starts_with?(difficulty)
        return [nonce, hash] # # bingo! proof of work if hash starts with leading zeros (00)
      else
        nonce += 1 # # keep trying (and trying and trying)
      end
    end
  end

  def calc_hash_with_nonce(nonce = 0)
    sha = OpenSSL::Digest.new("SHA256")
    sha.update(nonce.to_s + @index.to_s + @timestamp.to_s + @data + @previous_hash)
    sha.hexdigest
  end

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

  def self.next(previous, data = "Transaction Data...")
    Block.new(previous.index + 1, data, previous.hash)
  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]

puts blockchain

######
#  will print something like:
#
# [#<Block:0x1e204f0
#   @data="Genesis",
#   @hash="00b8e77e27378f9aa0afbcea3a2882bb62f6663771dee053364beb1887e18bcf",
#   @index=0,
#   @nonce=242,
#   @previous_hash="0",
#   @timestamp=2017-09-20 20:13:38 +0200>,
#  #<Block:0x1e56e20
#   @data="Transaction Data...",
#   @hash="00aae8d2e9387e13c71b33f8cd205d336ac250d2828011f5970062912985a9af",
#   @index=1,
#   @nonce=46,
#   @previous_hash=
#    "00b8e77e27378f9aa0afbcea3a2882bb62f6663771dee053364beb1887e18bcf",
#   @timestamp=2017-09-20 20:13:38 +0200>,
#  #<Block:0x1e2bd58
#   @data="Transaction Data......",
#   @hash="00ea45e0f4683c3bec4364f349ee2b6816be0c9fd95cfd5ffcc6ed572c62f190",
#   @index=2,
#   @nonce=350,
#   @previous_hash=
#    "00aae8d2e9387e13c71b33f8cd205d336ac250d2828011f5970062912985a9af",
#   @timestamp=2017-09-20 20:13:38 +0200>,
#  #<Block:0x1fa8338
#   @data="More Transaction Data...",
#   @hash="00436f0fca677652963e904ce4c624606a255946b921132d5b1f70f7d86c4ab8",
#   @index=3,
#   @nonce=59,
#   @previous_hash=
#    "00ea45e0f4683c3bec4364f349ee2b6816be0c9fd95cfd5

However when I run it I get an error that states:

Error in blockchain.cr/blockchain_with_proof_of_work.cr:57: instantiating 
'Block:Class#first(String)'

b0 = Block.first("Genesis")
           ^~~~~

in blockchain.cr/blockchain_with_proof_of_work.cr:45: instantiating 
'Block:Class#new(Int32, String, String)'

Block.new(0, data, "0")
      ^~~

in blockchain.cr/blockchain_with_proof_of_work.cr:22: instance variable 
'@nonce' of Block must be Int32, not (Int32 | String)

    @nonce, @hash = compute_hash_with_proof_of_work
    ^~~~~~

Aug 10, 2018 in Blockchain by sabby
• 4,370 points
897 views

1 answer to this question.

0 votes

When decomposing an Array into a multiple assignment Crystal can't infer the exact type of each element. So the value assigned to the instance variable @nonce could be either Int32 or String. You should use a Tuple instead: return {nonce, hash} (in line 29). A tuple has positional type declarations and is by the way more performant than an Array because it does not allocate memory on the heap.

answered Aug 10, 2018 by Perry
• 17,100 points

Related Questions In Blockchain

+1 vote
1 answer

How do i change the names of validating peers in IBM Bluemix blockchain?

IBM Bluemix Blockchain service Hyperledger Fabric v0.6 will ...READ MORE

answered Apr 11, 2018 in Blockchain by Perry
971 views
0 votes
1 answer
0 votes
1 answer

How do I use hyperledger fabric blockchain to build my own application?

To use fabric I would recommend you ...READ MORE

answered May 17, 2018 in Blockchain by Johnathon
• 9,090 points
1,076 views
0 votes
1 answer

Truffle tests not running after truffle init

This was a bug. They've fixed it. ...READ MORE

answered Sep 11, 2018 in Blockchain by Christine
• 15,790 points
1,923 views
+1 vote
3 answers

Removing double quotes from a string from JSON response in PHP

Just remove the json_encode call, and it should work: $resp ...READ MORE

answered Sep 12, 2018 in Blockchain by digger
• 26,740 points
45,219 views
0 votes
1 answer

Hyperledger Sawtooth vs Quorum in concurrency and speed Ask

Summary: Both should provide similar reliability of ...READ MORE

answered Sep 26, 2018 in IoT (Internet of Things) by Upasana
• 8,620 points
1,451 views
0 votes
1 answer

How do I send back ethers to the sender of the tokens in a smart contract?

Whenever a smart contract receives ether via ...READ MORE

answered May 30, 2018 in Blockchain by Perry
• 17,100 points
3,602 views
0 votes
1 answer

How do I add multiple recipients for transactions via Blockchain API?

Convert the recipes into JSON objects. x = ...READ MORE

answered Jul 6, 2018 in Blockchain by Perry
• 17,100 points
886 views
webinar REGISTER FOR FREE WEBINAR X
REGISTER NOW
webinar_success Thank you for registering Join Edureka Meetup community for 100+ Free Webinars each month JOIN MEETUP GROUP