-
Notifications
You must be signed in to change notification settings - Fork 440
/
blockchain_with_proof_of_work.rb
106 lines (88 loc) · 2.94 KB
/
blockchain_with_proof_of_work.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
###########################
# build your own blockchain from scratch in ruby!
#
# to run use:
# $ ruby ./blockchain_with_proof_of_work.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 :nonce ## proof of work if hash starts with leading zeros (00)
attr_reader :hash
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.start_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 = Digest::SHA256.new
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]
pp blockchain
######
# will pretty print (pp) 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=
# "00ea45e0f4683c3bec4364f349ee2b6816be0c9fd95cfd5ffcc6ed572c62f190",
# @timestamp=2017-09-20 20:13:38 +0200>]