tierion 1.0.0 → 1.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 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