merkletree 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Manifest.txt +4 -0
- data/README.md +143 -0
- data/Rakefile +2 -2
- data/lib/merkletree.rb +138 -4
- data/lib/merkletree/version.rb +4 -3
- data/test/helper.rb +10 -0
- data/test/test_build.rb +158 -0
- data/test/test_readme.rb +74 -0
- data/test/test_version.rb +21 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9bdd4412b5bb49cfa7d3f5d5d93d5f0254248952
|
4
|
+
data.tar.gz: 3759dac07a1eb87444a7264089a83a113ec62a18
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a99eb56b3472efcca00ea11d2b9a7dedc69903dc43d33cd5d9677dd737b32288a216fd6d5f1be9bf4b6b893c311034c9c30cc7ffd0f890e65827dd730f36881f
|
7
|
+
data.tar.gz: a0c2465fcb59581478779ef74bd05bf74642fb5b818072d53847fa949cdb66e8f127852edc5d99ef4ab4652d3a454ab850fbcc640a75bf6e73a91b5fc3f23594
|
data/Manifest.txt
CHANGED
data/README.md
CHANGED
@@ -9,6 +9,149 @@ merkletree library / gem - build your own crypto hash trees; named after Ralph M
|
|
9
9
|
* rdoc :: [rubydoc.info/gems/merkletree](http://rubydoc.info/gems/merkletree)
|
10
10
|
|
11
11
|
|
12
|
+
## What's a Merkle Tree?
|
13
|
+
|
14
|
+
> A Merkle tree or hash tree is a tree in which every leaf node is labelled with
|
15
|
+
> the hash of a data block and every non-leaf node is labelled with the
|
16
|
+
> cryptographic hash of the labels of its child nodes.
|
17
|
+
> Hash trees allow efficient and secure verification of the
|
18
|
+
> contents of large data structures. [...]
|
19
|
+
>
|
20
|
+
> The concept of hash trees is named after Ralph Merkle
|
21
|
+
> who patented it in 1979.
|
22
|
+
>
|
23
|
+
> -- [Wikipedia](https://en.wikipedia.org/wiki/Merkle_tree)
|
24
|
+
|
25
|
+
|
26
|
+
## Usage
|
27
|
+
|
28
|
+
|
29
|
+
Pass along all (leaf / data block) hashes as strings or packaged in an array.
|
30
|
+
Example:
|
31
|
+
|
32
|
+
``` ruby
|
33
|
+
merkle = MerkleTree.new(
|
34
|
+
'eb8ecbf6d5870763ae246e37539d82e37052cb32f88bb8c59971f9978e437743',
|
35
|
+
'edbd4e11e69bc399a9ccd8faaea44fb27410fe8e3023bb9462450a0a9c4caa1b',
|
36
|
+
'5ee2981606328abfe0c3b1171440f0df746c1e1f8b3b56c351727f7da7ae5d8d' )
|
37
|
+
|
38
|
+
# -or-
|
39
|
+
|
40
|
+
merkle = MerkleTree.new( [
|
41
|
+
'eb8ecbf6d5870763ae246e37539d82e37052cb32f88bb8c59971f9978e437743',
|
42
|
+
'edbd4e11e69bc399a9ccd8faaea44fb27410fe8e3023bb9462450a0a9c4caa1b',
|
43
|
+
'5ee2981606328abfe0c3b1171440f0df746c1e1f8b3b56c351727f7da7ae5d8d' ])
|
44
|
+
|
45
|
+
|
46
|
+
puts 'merkle tree root hash:'
|
47
|
+
puts merkle.root.value
|
48
|
+
# => '25fd59b79d70bbdf043d66a7b0fc01409d11b990e943bb46b840fbbddd5ab895'
|
49
|
+
|
50
|
+
pp merkle ## pp (pretty print)
|
51
|
+
```
|
52
|
+
|
53
|
+
resulting in:
|
54
|
+
|
55
|
+
```
|
56
|
+
@root = #<MerkleTree::Node:0x46b55e0
|
57
|
+
@left = #<MerkleTree::Node:0x46b6060
|
58
|
+
@left = #<MerkleTree::Node:0x46b6870
|
59
|
+
@left = nil,
|
60
|
+
@right = nil,
|
61
|
+
@value = "eb8ecbf6d5870763ae246e37539d82e37052cb32f88bb8c59971f9978e437743">,
|
62
|
+
@right = #<MerkleTree::Node:0x46b6810
|
63
|
+
@left = nil,
|
64
|
+
@right = nil,
|
65
|
+
@value = "edbd4e11e69bc399a9ccd8faaea44fb27410fe8e3023bb9462450a0a9c4caa1b">,
|
66
|
+
@value = "c9de03ced4db3c63835807016b1efedb647c694d2db8b9a8579cbf0c5dcb5ab0">,
|
67
|
+
@right= #<MerkleTree::Node:0x46b5ca0
|
68
|
+
@left= #<MerkleTree::Node:0x46b6798
|
69
|
+
@left = nil,
|
70
|
+
@right = nil,
|
71
|
+
@value = "5ee2981606328abfe0c3b1171440f0df746c1e1f8b3b56c351727f7da7ae5d8d">,
|
72
|
+
@right = #<MerkleTree::Node:0x46b6798
|
73
|
+
@left = nil,
|
74
|
+
@right = nil,
|
75
|
+
@value = "5ee2981606328abfe0c3b1171440f0df746c1e1f8b3b56c351727f7da7ae5d8d">,
|
76
|
+
@value = "50963aa3b2047e0d58bb850fc12e5a324cf01061af55889389be72d3849e1d03">,
|
77
|
+
@value="25fd59b79d70bbdf043d66a7b0fc01409d11b990e943bb46b840fbbddd5ab895">>
|
78
|
+
```
|
79
|
+
|
80
|
+
|
81
|
+
Use `MerkleTree.compute_root` for computing the root (crypto) hash without building a
|
82
|
+
tree. Example:
|
83
|
+
|
84
|
+
``` ruby
|
85
|
+
merkle_root_value = MerkleTree.compute_root(
|
86
|
+
'eb8ecbf6d5870763ae246e37539d82e37052cb32f88bb8c59971f9978e437743',
|
87
|
+
'edbd4e11e69bc399a9ccd8faaea44fb27410fe8e3023bb9462450a0a9c4caa1b',
|
88
|
+
'5ee2981606328abfe0c3b1171440f0df746c1e1f8b3b56c351727f7da7ae5d8d' )
|
89
|
+
|
90
|
+
# -or-
|
91
|
+
|
92
|
+
merkle_root_value = MerkleTree.compute_root( [
|
93
|
+
'eb8ecbf6d5870763ae246e37539d82e37052cb32f88bb8c59971f9978e437743',
|
94
|
+
'edbd4e11e69bc399a9ccd8faaea44fb27410fe8e3023bb9462450a0a9c4caa1b',
|
95
|
+
'5ee2981606328abfe0c3b1171440f0df746c1e1f8b3b56c351727f7da7ae5d8d' ])
|
96
|
+
|
97
|
+
|
98
|
+
puts 'merkle tree root hash:'
|
99
|
+
puts merkle_root_value
|
100
|
+
# => '25fd59b79d70bbdf043d66a7b0fc01409d11b990e943bb46b840fbbddd5ab895'
|
101
|
+
```
|
102
|
+
|
103
|
+
|
104
|
+
### Transactions
|
105
|
+
|
106
|
+
Use `MerkleTree.for` or `MerkleTree.compute_root_for` for passing along transactions.
|
107
|
+
Will use `to_s` on every transaction and use the resulting "serialized" string
|
108
|
+
to (auto-) calculate the (crypto) hash.
|
109
|
+
|
110
|
+
Let's put the transactions from the (hyper) ledger book from [Tulips on the Blockchain!](https://github.com/openblockchains/tulips)
|
111
|
+
on the ~~blockchain~~ merkle tree:
|
112
|
+
|
113
|
+
|
114
|
+
| From | To | What | Qty |
|
115
|
+
|---------------------|--------------|---------------------------|----:|
|
116
|
+
| Bloom & Blossom (†) | Daisy | Tulip Admiral of Admirals | 8 |
|
117
|
+
| Vincent | Max | Tulip Bloemendaal Sunset | 2 |
|
118
|
+
| Anne | Martijn | Tulip Semper Augustus | 2 |
|
119
|
+
| Ruben | Julia | Tulip Admiral van Eijck | 2 |
|
120
|
+
|
121
|
+
(†): Grower Transaction - New Tulips on the Market!
|
122
|
+
|
123
|
+
``` ruby
|
124
|
+
merkle = MerkleTree.for(
|
125
|
+
{ from: "Bloom & Blossom", to: "Daisy", what: "Tulip Admiral of Admirals", qty: 8 },
|
126
|
+
{ from: "Vincent", to: "Max", what: "Tulip Bloemendaal Sunset", qty: 2 },
|
127
|
+
{ from: "Anne", to: "Martijn", what: "Tulip Semper Augustus", qty: 2 },
|
128
|
+
{ from: "Ruben", to: "Julia", what: "Tulip Admiral van Eijck", qty: 2 } )
|
129
|
+
|
130
|
+
puts 'merkle tree root hash:'
|
131
|
+
puts merkle.root.value
|
132
|
+
# => '703f44630117ef9b4ac20cb149ed8a0f06e4c3ed2a791e11e16a2fe7a7d0de3d'
|
133
|
+
|
134
|
+
# -or-
|
135
|
+
|
136
|
+
merkle_root_value = MerkleTree.compute_root_for(
|
137
|
+
{ from: "Bloom & Blossom", to: "Daisy", what: "Tulip Admiral of Admirals", qty: 8 },
|
138
|
+
{ from: "Vincent", to: "Max", what: "Tulip Bloemendaal Sunset", qty: 2 },
|
139
|
+
{ from: "Anne", to: "Martijn", what: "Tulip Semper Augustus", qty: 2 },
|
140
|
+
{ from: "Ruben", to: "Julia", what: "Tulip Admiral van Eijck", qty: 2 } )
|
141
|
+
|
142
|
+
puts 'merkle tree root hash:'
|
143
|
+
puts merkle_root_value
|
144
|
+
# => '703f44630117ef9b4ac20cb149ed8a0f06e4c3ed2a791e11e16a2fe7a7d0de3d'
|
145
|
+
```
|
146
|
+
|
147
|
+
|
148
|
+
## Install
|
149
|
+
|
150
|
+
Just install the gem:
|
151
|
+
|
152
|
+
```
|
153
|
+
$ gem install merkletree
|
154
|
+
```
|
12
155
|
|
13
156
|
|
14
157
|
## License
|
data/Rakefile
CHANGED
data/lib/merkletree.rb
CHANGED
@@ -3,10 +3,10 @@
|
|
3
3
|
require 'digest' # for hash checksum digest function SHA256
|
4
4
|
require 'pp' # for pp => pretty printer
|
5
5
|
|
6
|
-
require 'date'
|
7
|
-
require 'time'
|
8
|
-
require 'json'
|
9
|
-
require 'uri'
|
6
|
+
## require 'date'
|
7
|
+
## require 'time'
|
8
|
+
## require 'json'
|
9
|
+
## require 'uri'
|
10
10
|
|
11
11
|
|
12
12
|
|
@@ -14,6 +14,140 @@ require 'uri'
|
|
14
14
|
require 'merkletree/version' # note: let version always go first
|
15
15
|
|
16
16
|
|
17
|
+
class MerkleTree
|
18
|
+
|
19
|
+
class Node
|
20
|
+
attr_reader :value
|
21
|
+
attr_reader :left
|
22
|
+
attr_reader :right
|
23
|
+
|
24
|
+
def initialize( value, left, right )
|
25
|
+
@value = value
|
26
|
+
@left = left
|
27
|
+
@right = right
|
28
|
+
end
|
29
|
+
end # class Node
|
30
|
+
|
31
|
+
|
32
|
+
## convenience helpers
|
33
|
+
def self.for( *args )
|
34
|
+
if args.size == 1 && args[0].is_a?( Array )
|
35
|
+
transactions = args[0] ## "unwrap" array in array
|
36
|
+
else
|
37
|
+
transactions = args ## use "auto-wrapped" splat array
|
38
|
+
end
|
39
|
+
## for now use to_s for calculation hash
|
40
|
+
hashes = transactions.map { |tx| calc_hash( tx.to_s ) }
|
41
|
+
self.new( hashes )
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.compute_root_for( *args )
|
45
|
+
if args.size == 1 && args[0].is_a?( Array )
|
46
|
+
transactions = args[0] ## "unwrap" array in array
|
47
|
+
else
|
48
|
+
transactions = args ## use "auto-wrapped" splat array
|
49
|
+
end
|
50
|
+
|
51
|
+
## for now use to_s for calculation hash
|
52
|
+
hashes = transactions.map { |tx| calc_hash( tx.to_s ) }
|
53
|
+
self.compute_root( hashes )
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
attr_reader :root
|
59
|
+
attr_reader :leaves
|
60
|
+
|
61
|
+
def initialize( *args )
|
62
|
+
if args.size == 1 && args[0].is_a?( Array )
|
63
|
+
hashes = args[0] ## "unwrap" array in array
|
64
|
+
else
|
65
|
+
hashes = args ## use "auto-wrapped" splat array
|
66
|
+
end
|
67
|
+
|
68
|
+
@hashes = hashes
|
69
|
+
@root = build_tree
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
def build_tree
|
74
|
+
level = @leaves = @hashes.map { |hash| Node.new( hash, nil, nil ) }
|
75
|
+
|
76
|
+
## todo/fix: handle hashes.size == 0 case
|
77
|
+
## - throw exception - why? why not?
|
78
|
+
## - return empty node with hash '0' - why? why not?
|
79
|
+
|
80
|
+
if @hashes.size == 1
|
81
|
+
level[0]
|
82
|
+
else
|
83
|
+
## while there's more than one hash in the layer, keep looping...
|
84
|
+
while level.size > 1
|
85
|
+
## loop through hashes two at a time
|
86
|
+
level = level.each_slice(2).map do |left, right|
|
87
|
+
## note: handle special case
|
88
|
+
# if number of nodes is odd e.g. 3,5,7,etc.
|
89
|
+
# last right node is nil -- duplicate node value for hash
|
90
|
+
## todo/check - duplicate just hash? or add right node ref too - why? why not?
|
91
|
+
right = left if right.nil?
|
92
|
+
|
93
|
+
Node.new( MerkleTree.calc_hash( left.value + right.value ), left, right)
|
94
|
+
end
|
95
|
+
## debug output
|
96
|
+
## puts "current merkle hash level (#{level.size} nodes):"
|
97
|
+
## pp level
|
98
|
+
end
|
99
|
+
### finally we end up with a single hash
|
100
|
+
level[0]
|
101
|
+
end
|
102
|
+
end # method build tree
|
103
|
+
|
104
|
+
|
105
|
+
|
106
|
+
### shortcut/convenience - compute root hash w/o building tree nodes
|
107
|
+
def self.compute_root( *args )
|
108
|
+
if args.size == 1 && args[0].is_a?( Array )
|
109
|
+
hashes = args[0] ## "unwrap" array in array
|
110
|
+
else
|
111
|
+
hashes = args ## use "auto-wrapped" splat array
|
112
|
+
end
|
113
|
+
|
114
|
+
## todo/fix: handle hashes.size == 0 case
|
115
|
+
## - throw exception - why? why not?
|
116
|
+
## - return empty node with hash '0' - why? why not?
|
117
|
+
|
118
|
+
if hashes.size == 1
|
119
|
+
hashes[0]
|
120
|
+
else
|
121
|
+
## while there's more than one hash in the list, keep looping...
|
122
|
+
while hashes.size > 1
|
123
|
+
# if number of hashes is odd e.g. 3,5,7,etc., duplicate last hash in list
|
124
|
+
hashes << hashes[-1] if hashes.size % 2 != 0
|
125
|
+
|
126
|
+
## loop through hashes two at a time
|
127
|
+
hashes = hashes.each_slice(2).map do |left,right|
|
128
|
+
## join both hashes slice[0]+slice[1] together
|
129
|
+
hash = calc_hash( left + right )
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
## debug output
|
134
|
+
## puts "current merkle hashes (#{hashes.size}):"
|
135
|
+
## pp hashes
|
136
|
+
### finally we end up with a single hash
|
137
|
+
hashes[0]
|
138
|
+
end
|
139
|
+
end # method compute_root
|
140
|
+
|
141
|
+
|
142
|
+
def self.calc_hash( data )
|
143
|
+
sha = Digest::SHA256.new
|
144
|
+
sha.update( data )
|
145
|
+
sha.hexdigest
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
end # class MerkleTree
|
150
|
+
|
17
151
|
|
18
152
|
# say hello
|
19
153
|
puts MerkleTree.banner if defined?($RUBYLIBS_DEBUG) && $RUBYLIBS_DEBUG
|
data/lib/merkletree/version.rb
CHANGED
data/test/helper.rb
ADDED
data/test/test_build.rb
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
###
|
4
|
+
# to run use
|
5
|
+
# ruby -I ./lib -I ./test test/test_build.rb
|
6
|
+
|
7
|
+
|
8
|
+
require 'helper'
|
9
|
+
|
10
|
+
|
11
|
+
class TestBuild < MiniTest::Test
|
12
|
+
|
13
|
+
|
14
|
+
def test_example_4
|
15
|
+
|
16
|
+
hashes = [
|
17
|
+
'00',
|
18
|
+
'11',
|
19
|
+
'22',
|
20
|
+
'33',
|
21
|
+
]
|
22
|
+
|
23
|
+
hash00 = '00'
|
24
|
+
hash11 = '11'
|
25
|
+
hash0011 = MerkleTree.calc_hash( hash00 + hash11 )
|
26
|
+
|
27
|
+
hash22 = '22'
|
28
|
+
hash33 = '33'
|
29
|
+
hash2233 = MerkleTree.calc_hash( hash22 + hash33 )
|
30
|
+
|
31
|
+
hash00112233 = MerkleTree.calc_hash( hash0011 + hash2233 )
|
32
|
+
|
33
|
+
|
34
|
+
merkle = MerkleTree.new( hashes )
|
35
|
+
|
36
|
+
puts "merkletree root hash:"
|
37
|
+
puts merkle.root.value
|
38
|
+
|
39
|
+
puts "merkletree:"
|
40
|
+
pp merkle.root
|
41
|
+
|
42
|
+
assert_equal hash00, merkle.root.left.left.value
|
43
|
+
assert_equal hash11, merkle.root.left.right.value
|
44
|
+
assert_equal hash22, merkle.root.right.left.value
|
45
|
+
assert_equal hash33, merkle.root.right.right.value
|
46
|
+
|
47
|
+
assert_equal hash0011, merkle.root.left.value
|
48
|
+
assert_equal hash2233, merkle.root.right.value
|
49
|
+
|
50
|
+
assert_equal hash00112233, merkle.root.value
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
merkle_root_value = MerkleTree.compute_root( hashes )
|
55
|
+
puts "merkletree root hash:"
|
56
|
+
puts merkle_root_value
|
57
|
+
|
58
|
+
assert_equal merkle.root.value, merkle_root_value
|
59
|
+
end # method test_example_4
|
60
|
+
|
61
|
+
|
62
|
+
def test_example_3 ## test odd (not even hashes)
|
63
|
+
|
64
|
+
hashes = [
|
65
|
+
'00',
|
66
|
+
'11',
|
67
|
+
'22',
|
68
|
+
]
|
69
|
+
|
70
|
+
hash00 = '00'
|
71
|
+
hash11 = '11'
|
72
|
+
hash0011 = MerkleTree.calc_hash( hash00 + hash11 )
|
73
|
+
|
74
|
+
hash22 = '22'
|
75
|
+
hash2222 = MerkleTree.calc_hash( hash22 + hash22 )
|
76
|
+
|
77
|
+
hash00112222 = MerkleTree.calc_hash( hash0011 + hash2222 )
|
78
|
+
|
79
|
+
|
80
|
+
merkle = MerkleTree.new( hashes )
|
81
|
+
|
82
|
+
puts "merkletree root hash:"
|
83
|
+
puts merkle.root.value
|
84
|
+
|
85
|
+
puts "merkletree:"
|
86
|
+
pp merkle.root
|
87
|
+
|
88
|
+
assert_equal hash00, merkle.root.left.left.value
|
89
|
+
assert_equal hash11, merkle.root.left.right.value
|
90
|
+
assert_equal hash22, merkle.root.right.left.value
|
91
|
+
assert_equal hash22, merkle.root.right.right.value
|
92
|
+
|
93
|
+
assert_equal hash0011, merkle.root.left.value
|
94
|
+
assert_equal hash2222, merkle.root.right.value
|
95
|
+
|
96
|
+
assert_equal hash00112222, merkle.root.value
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
merkle_root_value = MerkleTree.compute_root( hashes )
|
101
|
+
puts "merkletree root hash:"
|
102
|
+
puts merkle_root_value
|
103
|
+
|
104
|
+
assert_equal merkle.root.value, merkle_root_value
|
105
|
+
end # method test_example_3
|
106
|
+
|
107
|
+
|
108
|
+
def test_example_5 ## test odd (not even hashes)
|
109
|
+
|
110
|
+
hashes = [
|
111
|
+
'0000',
|
112
|
+
'0011',
|
113
|
+
'0022',
|
114
|
+
'0033',
|
115
|
+
'0044',
|
116
|
+
]
|
117
|
+
|
118
|
+
merkle = MerkleTree.new( hashes )
|
119
|
+
|
120
|
+
puts "merkletree root hash:"
|
121
|
+
puts merkle.root.value
|
122
|
+
|
123
|
+
puts "merkletree:"
|
124
|
+
pp merkle.root
|
125
|
+
|
126
|
+
|
127
|
+
merkle_root_value = MerkleTree.compute_root( hashes )
|
128
|
+
puts "merkletree root hash:"
|
129
|
+
puts merkle_root_value
|
130
|
+
|
131
|
+
assert_equal merkle.root.value, merkle_root_value
|
132
|
+
end # method test_example_5
|
133
|
+
|
134
|
+
|
135
|
+
def test_tulips
|
136
|
+
|
137
|
+
merkle = MerkleTree.for(
|
138
|
+
{ from: "Dutchgrown", to: "Vincent", what: "Tulip Bloemendaal Sunset", qty: 10 },
|
139
|
+
{ from: "Keukenhof", to: "Anne", what: "Tulip Semper Augustus", qty: 7 } )
|
140
|
+
|
141
|
+
puts "merkletree root hash:"
|
142
|
+
puts merkle.root.value
|
143
|
+
|
144
|
+
puts "merkletree:"
|
145
|
+
pp merkle.root
|
146
|
+
|
147
|
+
merkle_root_value = MerkleTree.compute_root_for(
|
148
|
+
{ from: "Dutchgrown", to: "Vincent", what: "Tulip Bloemendaal Sunset", qty: 10 },
|
149
|
+
{ from: "Keukenhof", to: "Anne", what: "Tulip Semper Augustus", qty: 7 } )
|
150
|
+
|
151
|
+
puts "merkletree root hash:"
|
152
|
+
puts merkle_root_value
|
153
|
+
|
154
|
+
assert_equal merkle.root.value, merkle_root_value
|
155
|
+
end # method test_tulips
|
156
|
+
|
157
|
+
|
158
|
+
end # class TestBuild
|
data/test/test_readme.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
###
|
4
|
+
# to run use
|
5
|
+
# ruby -I ./lib -I ./test test/test_readme.rb
|
6
|
+
|
7
|
+
|
8
|
+
require 'helper'
|
9
|
+
|
10
|
+
|
11
|
+
class TestReadme < MiniTest::Test
|
12
|
+
|
13
|
+
|
14
|
+
def xxx_test_hashes
|
15
|
+
|
16
|
+
merkle1 = MerkleTree.new(
|
17
|
+
'eb8ecbf6d5870763ae246e37539d82e37052cb32f88bb8c59971f9978e437743',
|
18
|
+
'edbd4e11e69bc399a9ccd8faaea44fb27410fe8e3023bb9462450a0a9c4caa1b',
|
19
|
+
'5ee2981606328abfe0c3b1171440f0df746c1e1f8b3b56c351727f7da7ae5d8d' )
|
20
|
+
|
21
|
+
# -or-
|
22
|
+
|
23
|
+
puts merkle1.root.value
|
24
|
+
pp merkle1
|
25
|
+
|
26
|
+
merkle2 = MerkleTree.new( [
|
27
|
+
'eb8ecbf6d5870763ae246e37539d82e37052cb32f88bb8c59971f9978e437743',
|
28
|
+
'edbd4e11e69bc399a9ccd8faaea44fb27410fe8e3023bb9462450a0a9c4caa1b',
|
29
|
+
'5ee2981606328abfe0c3b1171440f0df746c1e1f8b3b56c351727f7da7ae5d8d' ])
|
30
|
+
|
31
|
+
pp merkle2
|
32
|
+
puts merkle2.root.value
|
33
|
+
|
34
|
+
assert_equal merkle1.root.value, merkle2.root.value
|
35
|
+
|
36
|
+
|
37
|
+
merkle_root_value = MerkleTree.compute_root(
|
38
|
+
'eb8ecbf6d5870763ae246e37539d82e37052cb32f88bb8c59971f9978e437743',
|
39
|
+
'edbd4e11e69bc399a9ccd8faaea44fb27410fe8e3023bb9462450a0a9c4caa1b',
|
40
|
+
'5ee2981606328abfe0c3b1171440f0df746c1e1f8b3b56c351727f7da7ae5d8d' )
|
41
|
+
|
42
|
+
puts merkle_root_value
|
43
|
+
|
44
|
+
assert_equal merkle1.root.value, merkle_root_value
|
45
|
+
end # method test_hashes
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
def test_transactions
|
50
|
+
|
51
|
+
merkle = MerkleTree.for(
|
52
|
+
{ from: "Bloom & Blossom", to: "Daisy", what: "Tulip Admiral of Admirals", qty: 8 },
|
53
|
+
{ from: "Vincent", to: "Max", what: "Tulip Bloemendaal Sunset", qty: 2 },
|
54
|
+
{ from: "Anne", to: "Martijn", what: "Tulip Semper Augustus", qty: 2 },
|
55
|
+
{ from: "Ruben", to: "Julia", what: "Tulip Admiral van Eijck", qty: 2 } )
|
56
|
+
|
57
|
+
puts 'merkle tree root hash:'
|
58
|
+
puts merkle.root.value
|
59
|
+
pp merkle
|
60
|
+
|
61
|
+
merkle_root_value = MerkleTree.compute_root_for(
|
62
|
+
{ from: "Bloom & Blossom", to: "Daisy", what: "Tulip Admiral of Admirals", qty: 8 },
|
63
|
+
{ from: "Vincent", to: "Max", what: "Tulip Bloemendaal Sunset", qty: 2 },
|
64
|
+
{ from: "Anne", to: "Martijn", what: "Tulip Semper Augustus", qty: 2 },
|
65
|
+
{ from: "Ruben", to: "Julia", what: "Tulip Admiral van Eijck", qty: 2 } )
|
66
|
+
|
67
|
+
puts 'merkle tree root hash:'
|
68
|
+
puts merkle_root_value
|
69
|
+
|
70
|
+
assert_equal merkle.root.value, merkle_root_value
|
71
|
+
end # method test_transactions
|
72
|
+
|
73
|
+
|
74
|
+
end # class TestReadme
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
###
|
4
|
+
# to run use
|
5
|
+
# ruby -I ./lib -I ./test test/test_version.rb
|
6
|
+
|
7
|
+
|
8
|
+
require 'helper'
|
9
|
+
|
10
|
+
|
11
|
+
class TestVersion < MiniTest::Test
|
12
|
+
|
13
|
+
def test_version
|
14
|
+
puts MerkleTree.version
|
15
|
+
puts MerkleTree.banner
|
16
|
+
puts MerkleTree.root
|
17
|
+
|
18
|
+
assert true ## (for now) everything ok if we get here
|
19
|
+
end
|
20
|
+
|
21
|
+
end # class TestVersion
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: merkletree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-12-
|
11
|
+
date: 2017-12-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rdoc
|
@@ -56,6 +56,10 @@ files:
|
|
56
56
|
- Rakefile
|
57
57
|
- lib/merkletree.rb
|
58
58
|
- lib/merkletree/version.rb
|
59
|
+
- test/helper.rb
|
60
|
+
- test/test_build.rb
|
61
|
+
- test/test_readme.rb
|
62
|
+
- test/test_version.rb
|
59
63
|
homepage: https://github.com/openblockchains/merkletree.rb
|
60
64
|
licenses:
|
61
65
|
- Public Domain
|