tierion 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7a6c61dbd6130591ba0ae23a7fa8845a8b2a4c8f
4
- data.tar.gz: d7023dcf234d38ae0b383eb51ab5480d69427c41
3
+ metadata.gz: b96becbb97f59db9528c8ab605507dbd4c7d45fe
4
+ data.tar.gz: 2ac8b5c71e817e92fae8654f54823d250dc4ebe8
5
5
  SHA512:
6
- metadata.gz: 39443a1eca9208226af6a56587ba863df0428a94f647c6d82dac1cdd122109c8a192fc7fa1034e6fb11f3c72780b8d0e9bc5a0e58774ffd8447516fa3b7d3b29
7
- data.tar.gz: 1060b935d65af04add356b0679f327cf6ce1175fc6d61cf18f93d4b3c073d4c63fbbd5e97811a81f8e366e97e6c63df8fe418fcc380dfb2bfae5bc28c02a2e30
6
+ metadata.gz: cc52a5336bcc9092391c0a544ad432400de3baa9486ca1613f3d91b0ad65cf76389da4e55a90b42707876c2609d8dd3c28eab1fe57da2a9a56ef9feb0c396d85
7
+ data.tar.gz: 3f23fa5db012de8031cc8c34acdae3d3b2d282f5ce936fabefd3b5713f3eb58a0a8fd726081a1819260924d28864c482b96b9a3421be6a9e2bf83d7accc3763a
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -1,5 +1,11 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v1.1.0 (8/6/2016)
4
+
5
+ - Added `Receipt#valid?` method to verify Merkle tree proof.
6
+ - Validates `Receipt` merkle tree and target hash match on import.
7
+ - Added support for blockchain subscription API's
8
+
3
9
  ## v1.0.0 (8/5/2016)
4
10
 
5
11
  - Refactor Ruby API to better match the Client, HashItem, Receipt, Confirmation hierarchy.
data/README.md CHANGED
@@ -22,6 +22,8 @@ Or install it yourself as:
22
22
 
23
23
  Shell commands start with a `$`, Ruby console commands start with `>`.
24
24
 
25
+ ### Client Authorization and Authentication
26
+
25
27
  Instantiate a new API client
26
28
 
27
29
  ```
@@ -42,6 +44,8 @@ $ export TIERION_PASSWORD=my_pass
42
44
  > t = Tierion::HashApi::Client.new
43
45
  ```
44
46
 
47
+ ### Send Hash
48
+
45
49
  Create the hash you want to record on the blockchain
46
50
  and send it.
47
51
 
@@ -53,6 +57,8 @@ and send it.
53
57
  => Tierion::HashApi::HashItem ...
54
58
  ```
55
59
 
60
+ ### Hash Items
61
+
56
62
  Now you can take a look at the Array of `HashItem`s.
57
63
 
58
64
  ```
@@ -81,6 +87,8 @@ the seconds since the UNIX epoch. For convenience you can use `HashItem#time` to
81
87
  => 2016-08-06 01:53:55 UTC
82
88
  ```
83
89
 
90
+ ### Receipts
91
+
84
92
  You can retrieve an individual `Tierion::HashApi::Receipt`
85
93
  for this `HashItem` by passing the `Hashitem` instance as
86
94
  an arg to `Client#receipt`
@@ -134,6 +142,16 @@ which are populated from the API. Here is an example:
134
142
  }
135
143
  ```
136
144
 
145
+ You can check the validity of the Merkle Tree proof with `Receipt#valid?`
146
+ which will do the math and hash the target hash with each of the proof hashes and verify that they hash properly and match the `merkleRoot` hash.
147
+
148
+ This requires no external API access and is done locally.
149
+
150
+ ```
151
+ > r.valid?
152
+ => true
153
+ ```
154
+
137
155
  The `Receipt` returns `anchors` which represent one or more trust
138
156
  anchors where your hash has been stored. Currently, the only `anchor`
139
157
  returned is `BTCOpReturn` which also gives you a `sourceId`
@@ -198,10 +216,34 @@ You can validate this JSON representation of the receipt by
198
216
  submitting it to the [Tierion validation](https://tierion.com/validate)
199
217
  web page.
200
218
 
201
- ## TODO
219
+ ### Block Subscriptions
220
+
221
+ You can also create, retrieve, update, and delete 'block subscriptions'.
202
222
 
203
- - Add blockchain receipt subscription functionality.
204
223
 
224
+ ```
225
+ > t = Tierion::HashApi::Client.new
226
+ => #<Tierion::HashApi::Client ... >
227
+
228
+ # takes a callback URL to receive payload, returns an ID
229
+ > t.create_block_subscription('https://www.rempe.us/foo')
230
+ => {:id=>"57a67d59fb16c5bc06f8d4e5"}
231
+
232
+ # takes an ID of an existing subscription and a new callback URL
233
+ # returns the new `callbackUrl`
234
+ > t.update_block_subscription("57a67d59fb16c5bc06f8d4e5", 'https://www.rempe.us/bar')
235
+ => {:callbackUrl=>"https://www.rempe.us/bar"}
236
+
237
+ # takes an ID of an existing subscription, returns
238
+ # the `callbackUrl`
239
+ > t.get_block_subscription("57a67d59fb16c5bc06f8d4e5")
240
+ => {:callbackUrl=>"https://www.rempe.us/bar"}
241
+
242
+ # takes an ID of an existing subscription, deletes it,
243
+ # and returns the `callbackUrl` of the subscription deleted.
244
+ > t.delete_block_subscription("57a67d59fb16c5bc06f8d4e5")
245
+ => {:callbackUrl=>"https://www.rempe.us/bar"}
246
+ ```
205
247
 
206
248
  ## Development
207
249
 
@@ -3,6 +3,7 @@ require 'active_support/core_ext/object/blank.rb'
3
3
  require 'active_support/core_ext/numeric'
4
4
  require 'active_support/core_ext/integer/time'
5
5
  require 'json'
6
+ require 'digest'
6
7
  require 'httparty'
7
8
  require 'hashie'
8
9
 
@@ -95,7 +95,12 @@ module Tierion
95
95
  Hashie.symbolize_keys!(receipt)
96
96
 
97
97
  if receipt.key?(:type) || receipt.key?('@type')
98
- Tierion::HashApi::Receipt.new(receipt)
98
+ r = Tierion::HashApi::Receipt.new(receipt)
99
+ if h.hash == r.targetHash && r.valid?
100
+ return r
101
+ else
102
+ raise 'Invalid Receipt returned'
103
+ end
99
104
  else
100
105
  raise 'Invalid Receipt found'
101
106
  end
@@ -110,6 +115,72 @@ module Tierion
110
115
  @expires_at >= Time.now.utc
111
116
  end
112
117
 
118
+ def create_block_subscription(callback_url)
119
+ auth_refresh unless logged_in?
120
+ options = {
121
+ body: { 'callbackUrl' => callback_url },
122
+ headers: { 'Authorization' => "Bearer #{@access_token}" }
123
+ }
124
+ response = self.class.post('/blocksubscriptions', options)
125
+
126
+ if response.success?
127
+ parsed = response.parsed_response
128
+ Hashie.symbolize_keys!(parsed)
129
+ return parsed
130
+ else
131
+ raise_error(response)
132
+ end
133
+ end
134
+
135
+ def get_block_subscription(id)
136
+ auth_refresh unless logged_in?
137
+ options = {
138
+ headers: { 'Authorization' => "Bearer #{@access_token}" }
139
+ }
140
+ response = self.class.get("/blocksubscriptions/#{id}", options)
141
+
142
+ if response.success?
143
+ parsed = response.parsed_response
144
+ Hashie.symbolize_keys!(parsed)
145
+ return parsed
146
+ else
147
+ raise_error(response)
148
+ end
149
+ end
150
+
151
+ def update_block_subscription(id, callback_url)
152
+ auth_refresh unless logged_in?
153
+ options = {
154
+ body: { 'callbackUrl' => callback_url },
155
+ headers: { 'Authorization' => "Bearer #{@access_token}" }
156
+ }
157
+ response = self.class.put("/blocksubscriptions/#{id}", options)
158
+
159
+ if response.success?
160
+ parsed = response.parsed_response
161
+ Hashie.symbolize_keys!(parsed)
162
+ return parsed
163
+ else
164
+ raise_error(response)
165
+ end
166
+ end
167
+
168
+ def delete_block_subscription(id)
169
+ auth_refresh unless logged_in?
170
+ options = {
171
+ headers: { 'Authorization' => "Bearer #{@access_token}" }
172
+ }
173
+ response = self.class.delete("/blocksubscriptions/#{id}", options)
174
+
175
+ if response.success?
176
+ parsed = response.parsed_response
177
+ Hashie.symbolize_keys!(parsed)
178
+ return parsed
179
+ else
180
+ raise_error(response)
181
+ end
182
+ end
183
+
113
184
  private
114
185
 
115
186
  def raise_error(response)
@@ -14,8 +14,44 @@ module Tierion
14
14
  @confs
15
15
  end
16
16
 
17
+ # Checks the validity of the Merkle tree proof and
18
+ # return true or false
19
+ def valid?
20
+ return false if targetHash.blank? || merkleRoot.blank?
21
+
22
+ # No siblings, single item tree, so the hash
23
+ # should also be the root
24
+ return targetHash == merkleRoot if proof.empty?
25
+
26
+ # The target hash (the hash the user submitted)
27
+ # is always hashed in the first cycle through the
28
+ # proofs. After that, the proof_hash value will
29
+ # contain intermediate hashes.
30
+ proof_hash = targetHash
31
+
32
+ proof.each do |p|
33
+ h = Digest::SHA256.new
34
+ if p.key?('left')
35
+ h.update hex2bin(p['left'])
36
+ h.update hex2bin(proof_hash)
37
+ elsif p.key?('right')
38
+ h.update hex2bin(proof_hash)
39
+ h.update hex2bin(p['right'])
40
+ else
41
+ return false
42
+ end
43
+ proof_hash = h.hexdigest
44
+ end
45
+
46
+ proof_hash == merkleRoot
47
+ end
48
+
17
49
  private
18
50
 
51
+ def hex2bin(hex)
52
+ [hex.to_s].pack('H*')
53
+ end
54
+
19
55
  def get_confirmations
20
56
  @confs = {} if @confs.blank?
21
57
 
@@ -1,3 +1,3 @@
1
1
  module Tierion
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.0'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tierion
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Glenn Rempe
@@ -30,7 +30,7 @@ cert_chain:
30
30
  zieXiXZSAojfFx9g91fKdIrlPbInHU/BaCxXSLBwvOM0drE+c2ue9X8gB55XAhzX
31
31
  37oBiw==
32
32
  -----END CERTIFICATE-----
33
- date: 2016-08-06 00:00:00.000000000 Z
33
+ date: 2016-08-07 00:00:00.000000000 Z
34
34
  dependencies:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: httparty
metadata.gz.sig CHANGED
Binary file