vchain_client 1.0.1 → 1.0.6

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: fa130280366a0e4e56548c9a15435e04db999452
4
- data.tar.gz: 4d18e892a688984d0687191cf2ea6420214613a8
3
+ metadata.gz: 22d66dc123ee989151f30fd3788b468c62026c78
4
+ data.tar.gz: 685b5f411fb7c965f493facc83d72ab886f9045d
5
5
  SHA512:
6
- metadata.gz: ed11a5f60b243789441434726c5724e24964cefaf5c4b0d36059723170396cbdc94bbf6f315a4d18016cb0a317ad52c4c631af382a8a213248aa97e2b350f269
7
- data.tar.gz: 414e34150172826ceab35559cb32d7fad5c1fe99256a526aa4e7613a6490caeb98c0e84475c3681cc685a2805898ce3c4711bf4711e3f53bae44efd9574aeb82
6
+ metadata.gz: 82145e5468d9b71fe0b9c95cc1b836ae06a9b53caecb5ed1e18a64e0be4562fd55a2246b22dc49a8485add020d45f763141e6c14dedf64e8301a1457d86b5fc8
7
+ data.tar.gz: d2ae23783d5ed7ae0b6519edffca250e63663c8d8b4cbde5b246f4d062eb31601ed0f34ef29616755e644a43769b4afb31babe90adb2cf2eaa79d5dffdb85215
@@ -2,6 +2,8 @@ module VChainClient
2
2
 
3
3
  class BitcoindBlockchainAdapter < VChainClient::BlockchainAdapter
4
4
 
5
+ @log = nil
6
+
5
7
  @server = nil
6
8
  @port = nil
7
9
  @rpc_username = nil
@@ -12,22 +14,76 @@ module VChainClient
12
14
  @port = port
13
15
  @rpc_username = rpc_username
14
16
  @rpc_password = rpc_password
17
+
18
+ @log = Log4r::Logger["vchain_client"]
15
19
  end
16
20
 
21
+ def getName()
22
+ return "BitcoindBlockchainAdapter"
23
+ end
24
+
17
25
  def getTx(txid)
18
- raw_tx = self.getRawTx(txid)
26
+
27
+ if @log.debug?
28
+ @log.debug("[Bitcoind.getTx] input:")
29
+ @log.debug("-> txid: #{txid}")
30
+ @log.debug("-> server: #{@server}")
31
+ @log.debug("-> port: #{@port}")
32
+ end
33
+
34
+ raw_tx = nil
35
+
36
+ begin
37
+
38
+ raw_tx = self.getRawTx(txid)
39
+
40
+ rescue => e
41
+ if @log.error?
42
+ @log.error("[Bitcoind.getTx] getRawTx raised exception:")
43
+ @log.error("#{e.class}, #{e.message}")
44
+ @log.error("-> txid: #{txid}")
45
+ @log.error("-> server: #{@server}")
46
+ @log.error("-> port: #{@port}")
47
+ @log.error("--> txid: #{txid}")
48
+ end
49
+
50
+ raise e
51
+ end
19
52
 
20
53
  if raw_tx != nil
54
+
21
55
  if raw_tx.key?("confirmations")
56
+
22
57
  if raw_tx["confirmations"] > 5
58
+
23
59
  if raw_tx.key?("blockhash")
60
+
24
61
  if raw_tx.key?("blocktime")
25
62
 
26
- op_return = self.getOpReturn(raw_tx)
63
+ op_return = nil
64
+
65
+ begin
66
+
67
+ op_return = self.getOpReturn(raw_tx)
68
+
69
+ rescue => e
70
+ if @log.error?
71
+ @log.error("[Bitcoind.getTx] getOpReturn raised exception:")
72
+ @log.error("#{e.class}, #{e.message}")
73
+ @log.error("-> txid: #{txid}")
74
+ @log.error("--> raw_tx:")
75
+ @log.error(raw_tx)
76
+ end
77
+
78
+ raise e
79
+ end
27
80
 
28
81
  if op_return != nil
82
+
29
83
  prefix = op_return[0..2]
84
+
30
85
  if prefix == "VCH"
86
+
31
87
  op_return = op_return[3..op_return.length]
32
88
 
33
89
  return {
@@ -36,19 +92,95 @@ module VChainClient
36
92
  "block_timestamp" => raw_tx["blocktime"],
37
93
  "op_return" => op_return
38
94
  }
95
+
96
+ else
97
+ if @log.error?
98
+ @log.error("[Bitcoind.getTx] wrong prefix '#{prefix}'")
99
+ @log.error("-> txid: #{txid}")
100
+ @log.error("-> server: #{@server}")
101
+ @log.error("-> port: #{@port}")
102
+ @log.error("-> raw_tx:")
103
+ @log.error(raw_tx)
104
+ end
105
+ end
106
+
107
+ else
108
+ if @log.error?
109
+ @log.error("[Bitcoind.getTx] failed to get OP_RETURN")
110
+ @log.error("-> txid: #{txid}")
111
+ @log.error("-> server: #{@server}")
112
+ @log.error("-> port: #{@port}")
113
+ @log.error("-> raw_tx:")
114
+ @log.error(raw_tx)
39
115
  end
40
116
  end
41
117
 
118
+ else
119
+ if @log.error?
120
+ @log.error("[Bitcoind.getTx] no 'block_hash' field in response")
121
+ @log.error("-> txid: #{txid}")
122
+ @log.error("-> server: #{@server}")
123
+ @log.error("-> port: #{@port}")
124
+ @log.error("-> raw_tx:")
125
+ @log.error(raw_tx)
126
+ end
127
+ end
128
+
129
+ else
130
+ if @log.error?
131
+ @log.error("[Bitcoind.getTx] no 'block_hash' field in response")
132
+ @log.error("-> txid: #{txid}")
133
+ @log.error("-> server: #{@server}")
134
+ @log.error("-> port: #{@port}")
135
+ @log.error("-> raw_tx:")
136
+ @log.error(raw_tx)
42
137
  end
43
138
  end
139
+
140
+ else
141
+ if @log.error?
142
+ @log.error("[Bitcoind.getTx] less than 6 confirmations")
143
+ @log.error("-> txid: #{txid}")
144
+ @log.error("-> server: #{@server}")
145
+ @log.error("-> port: #{@port}")
146
+ @log.error("-> raw_tx:")
147
+ @log.error(raw_tx)
148
+ end
149
+ end
150
+
151
+ else
152
+ if @log.error?
153
+ @log.error("[Bitcoind.getTx] no 'confirmations' field")
154
+ @log.error("-> txid: #{txid}")
155
+ @log.error("-> server: #{@server}")
156
+ @log.error("-> port: #{@port}")
157
+ @log.error("-> raw_tx:")
158
+ @log.error(raw_tx)
44
159
  end
45
160
  end
161
+
162
+ else
163
+ if @log.error?
164
+ @log.error("[Bitcoind.getTx] empty raw_tx")
165
+ @log.error("-> txid: #{txid}")
166
+ @log.error("-> server: #{@server}")
167
+ @log.error("-> port: #{@port}")
168
+ @log.error("--> txid: #{txid}")
169
+ end
46
170
  end
47
171
 
48
172
  return nil
49
173
  end
50
174
 
51
175
  def getRawTx(txid)
176
+
177
+ if @log.debug?
178
+ @log.debug("[Bitcoind.getRawTx] input:")
179
+ @log.debug("-> txid: #{txid}")
180
+ @log.debug("-> server: #{@server}")
181
+ @log.debug("-> port: #{@port}")
182
+ end
183
+
52
184
  request = {
53
185
  "id" => Random.rand(0...999999),
54
186
  "method" => "getrawtransaction",
@@ -62,14 +194,38 @@ module VChainClient
62
194
  req = RestClient.post(url, request.to_json)
63
195
 
64
196
  if req.code != 200
197
+ if @log.error?
198
+ @log.error("[Bitcoind.getRawTx] RestClient.post return code "+ req.code)
199
+ @log.error("-> txid: #{txid}")
200
+ @log.error("-> server: #{@server}")
201
+ @log.error("-> port: #{@port}")
202
+ @log.error("-> request:")
203
+ @log.error(request)
204
+ end
205
+
65
206
  return nil
66
207
  end
67
208
 
209
+ if @log.debug?
210
+ @log.debug("[Bitcoind.getRawTx] response:")
211
+ @log.debug(req.body)
212
+ end
213
+
68
214
  raw_tx = JSON.parse req.body
69
215
 
70
216
  return raw_tx["result"]
71
217
 
72
218
  rescue => e
219
+ if @log.error?
220
+ @log.error("[Bitcoind.getRawTx] RestClient.post raised exception:")
221
+ @log.error("#{e.class}, #{e.message}")
222
+ @log.error("-> txid: #{txid}")
223
+ @log.error("-> server: #{@server}")
224
+ @log.error("-> port: #{@port}")
225
+ @log.error("-> request:")
226
+ @log.error(request)
227
+ end
228
+
73
229
  raise e
74
230
  end
75
231
 
@@ -77,12 +233,22 @@ module VChainClient
77
233
  end
78
234
 
79
235
  def getOpReturn(raw_tx)
236
+
237
+ if @log.debug?
238
+ @log.debug("[Bitcoind.getOpReturn] input:")
239
+ @log.debug("-> raw_tx:")
240
+ @log.debug(raw_tx)
241
+ end
242
+
80
243
  if raw_tx != nil
244
+
81
245
  tx_unpacked = {}
82
246
  tx_unpacked["vout"] = []
83
247
 
84
248
  if raw_tx.key?("vout")
249
+
85
250
  if raw_tx["vout"].length > 0
251
+
86
252
  raw_tx["vout"].each_with_index { |vout,index|
87
253
  vout_t = {}
88
254
 
@@ -120,11 +286,17 @@ module VChainClient
120
286
  return scriptPubKeyBinary[4..scriptPubKeyBinary[2].ord()+1+256*scriptPubKeyBinary[3].ord()+1]
121
287
  end
122
288
  end
123
-
124
289
  }
125
290
 
126
291
  end
127
292
  end
293
+
294
+ else
295
+ if @log.error?
296
+ @log.error("[Bitcoind.getOpReturn] raw_tx is nil")
297
+ @log.error("-> raw_tx:")
298
+ @log.error(raw_tx)
299
+ end
128
300
  end
129
301
 
130
302
  return nil
@@ -6,6 +6,10 @@ module VChainClient
6
6
  return nil
7
7
  end
8
8
 
9
+ def getName()
10
+ return "abstract"
11
+ end
12
+
9
13
  end
10
14
 
11
15
  end
@@ -10,7 +10,8 @@ module VChainClient
10
10
  return VChainClient::BlockcypherBlockchainAdapter.new(config["api_token"])
11
11
  end
12
12
 
13
- return nil
13
+ raise "No such adapter '#{type}'"
14
+
14
15
  end
15
16
 
16
17
  end
@@ -2,23 +2,62 @@ module VChainClient
2
2
 
3
3
  class BlockchainConnection
4
4
 
5
+ @log = nil
6
+
5
7
  @config = nil
6
8
 
7
9
  def initialize(config)
8
10
  @config = config
11
+
12
+ @log = Log4r::Logger["vchain_client"]
9
13
  end
10
14
 
11
15
  def getTx(txid)
12
16
 
17
+ if @log.debug?
18
+ @log.debug("[BlockchainConnection.getTx] input:")
19
+ @log.debug("-> txid: #{txid}")
20
+ end
21
+
13
22
  adapters = []
14
23
 
24
+ if !@config.key?("blockchain_adapters")
25
+ raise "There are no blockchain_adapters in config"
26
+ end
27
+
15
28
  config_adapters = @config["blockchain_adapters"]
16
29
 
30
+ if config_adapters.length <= 0
31
+ raise "There are no blockchain_adapters in config"
32
+ end
33
+
17
34
  config_adapters.each { |adapter_config|
18
- adapter = VChainClient::BlockchainAdapterFactory.getAdapter(adapter_config["type"], adapter_config)
35
+
36
+ begin
37
+
38
+ adapter = VChainClient::BlockchainAdapterFactory.getAdapter(adapter_config["type"], adapter_config)
39
+
40
+ rescue => e
41
+ if @log.error?
42
+ @log.error("[BlockchainConnection.getTx] BlockchainAdapterFactory.getAdapter raised exception:")
43
+ @log.error("#{e.class}, #{e.message}")
44
+ @log.error("-> txid: #{txid}")
45
+ @log.error("--> type: "+ adapter_config["type"])
46
+ end
47
+
48
+ raise e
49
+ end
19
50
 
20
51
  if adapter != nil
21
- adapters.push(adapter)
52
+
53
+ adapters.push(adapter)
54
+
55
+ else
56
+ if @log.error?
57
+ @log.error("[BlockchainConnection.getTx] failed to init BlockchainAdapter")
58
+ @log.error("-> txid: #{txid}")
59
+ @log.error("--> type: "+ adapter_config["type"])
60
+ end
22
61
  end
23
62
  }
24
63
 
@@ -31,18 +70,65 @@ module VChainClient
31
70
 
32
71
  adapters.each { |adapter|
33
72
 
34
- tx = adapter.getTx(txid)
73
+ tx = nil
74
+
75
+ begin
76
+
77
+ tx = adapter.getTx(txid)
78
+
79
+ rescue => e
80
+ if @log.error?
81
+ @log.error("[BlockchainConnection.getTx] adapter.getTx raised exception:")
82
+ @log.error("#{e.class}, #{e.message}")
83
+ @log.error("-> txid: #{txid}")
84
+ @log.error("--> txid: #{txid}")
85
+ @log.error("--> adapter: "+ adapter.getName())
86
+ end
87
+
88
+ raise e
89
+ end
35
90
 
36
91
  if tx == nil
92
+ if @log.error?
93
+ @log.error("[BlockchainConnection.getTx] failed to get tx")
94
+ @log.error("-> txid: #{txid}")
95
+ @log.error("--> txid: #{txid}")
96
+ @log.error("--> adapter: "+ adapter.getName())
97
+ end
98
+
37
99
  return nil
38
100
  end
101
+
39
102
  if !tx.key?("block_hash")
103
+ if @log.error?
104
+ @log.error("[BlockchainConnection.getTx] no 'block_hash' field")
105
+ @log.error("-> txid: #{txid}")
106
+ @log.error("--> txid: #{txid}")
107
+ @log.error("--> adapter: "+ adapter.getName())
108
+ end
109
+
40
110
  return nil
41
111
  end
112
+
42
113
  if !tx.key?("block_timestamp")
114
+ if @log.error?
115
+ @log.error("[BlockchainConnection.getTx] no 'block_timestamp' field")
116
+ @log.error("-> txid: #{txid}")
117
+ @log.error("--> txid: #{txid}")
118
+ @log.error("--> adapter: "+ adapter.getName())
119
+ end
120
+
43
121
  return nil
44
122
  end
123
+
45
124
  if tx["block_hash"] == nil || tx["block_hash"] == ""
125
+ if @log.error?
126
+ @log.error("[BlockchainConnection.getTx] 'block_hash' field is empty")
127
+ @log.error("-> txid: #{txid}")
128
+ @log.error("--> txid: #{txid}")
129
+ @log.error("--> adapter: "+ adapter.getName())
130
+ end
131
+
46
132
  return nil
47
133
  end
48
134
 
@@ -52,15 +138,46 @@ module VChainClient
52
138
  op_return = tx["op_return"]
53
139
 
54
140
  if prev_size != nil && prev_size != size
141
+ if @log.error?
142
+ @log.error("[BlockchainConnection.getTx] size mismatch")
143
+ @log.error("-> txid: #{txid}")
144
+ @log.error("--> txid: #{txid}")
145
+ @log.error("--> adapter: "+ adapter.getName())
146
+ end
147
+
55
148
  return nil
56
149
  end
150
+
57
151
  if prev_block_hash != nil && prev_block_hash != block_hash
152
+ if @log.error?
153
+ @log.error("[BlockchainConnection.getTx] block_hash mismatch")
154
+ @log.error("-> txid: #{txid}")
155
+ @log.error("--> txid: #{txid}")
156
+ @log.error("--> adapter: "+ adapter.getName())
157
+ end
158
+
58
159
  return nil
59
160
  end
161
+
60
162
  if prev_block_timestamp != nil && prev_block_timestamp != block_timestamp
163
+ if @log.error?
164
+ @log.error("[BlockchainConnection.getTx] block_timestamp mismatch")
165
+ @log.error("-> txid: #{txid}")
166
+ @log.error("--> txid: #{txid}")
167
+ @log.error("--> adapter: "+ adapter.getName())
168
+ end
169
+
61
170
  return nil
62
171
  end
172
+
63
173
  if prev_op_return != nil && prev_op_return != op_return
174
+ if @log.error?
175
+ @log.error("[BlockchainConnection.getTx] op_return mismatch")
176
+ @log.error("-> txid: #{txid}")
177
+ @log.error("--> txid: #{txid}")
178
+ @log.error("--> adapter: "+ adapter.getName())
179
+ end
180
+
64
181
  return nil
65
182
  end
66
183
 
@@ -75,6 +192,9 @@ module VChainClient
75
192
  "block_timestamp" => prev_block_timestamp,
76
193
  "op_return" => prev_op_return
77
194
  }
195
+
196
+ else
197
+ raise "There are no initialized blockchain_adapters"
78
198
  end
79
199
 
80
200
  return nil
@@ -2,36 +2,134 @@ module VChainClient
2
2
 
3
3
  class BlockcypherBlockchainAdapter < VChainClient::BlockchainAdapter
4
4
 
5
+ @log = nil
6
+
5
7
  @api_token = nil
6
8
 
7
9
  def initialize(api_token)
8
10
  @api_token = api_token
11
+
12
+ @log = Log4r::Logger["vchain_client"]
9
13
  end
10
14
 
15
+ def getName()
16
+ return "BlockcypherBlockchainAdapter"
17
+ end
18
+
11
19
  def getTx(txid)
12
20
  url = "https://api.blockcypher.com/v1/btc/main/txs/"
13
21
  url += txid
14
22
  url += "?token="+ @api_token
15
23
  url += "&rand="+ Random.rand(0...999999).to_s
16
24
 
17
- req = RestClient.get(url)
25
+ if @log.debug?
26
+ @log.debug("[Blockcypher.getTx] input:")
27
+ @log.debug("-> txid: #{txid}")
28
+
29
+ @log.debug("[Blockcypher.getTx] will call '#{url}'")
30
+ end
31
+
32
+ req = nil
33
+
34
+ begin
35
+
36
+ req = RestClient.get(url)
37
+
38
+ rescue => e
39
+ if @log.error?
40
+ @log.error("[Blockcypher.getTx] RestClient.get raised exception:")
41
+ @log.error("#{e.class}, #{e.message}")
42
+ @log.error("-> txid: #{txid}")
43
+ @log.error("--> url: #{url}")
44
+ end
45
+
46
+ raise e
47
+ end
48
+
49
+ if req == nil
50
+ if @log.error?
51
+ @log.error("[Blockcypher.getTx] failed to call REST")
52
+ @log.error("-> txid: #{txid}")
53
+ @log.error("--> url: #{url}")
54
+ end
55
+
56
+ return nil
57
+ end
18
58
 
19
59
  if req.code != 200
60
+ if @log.error?
61
+ @log.error("[Blockcypher.getTx] REST call returned "+ req.code.to_s)
62
+ @log.error("-> txid: #{txid}")
63
+ @log.error("--> url: #{url}")
64
+ end
65
+
20
66
  return nil
21
67
  end
22
68
 
69
+ if @log.debug?
70
+ @log.debug("[Blockcypher.getTx] REST call response:")
71
+ @log.debug(req.body)
72
+ end
73
+
23
74
  res = JSON.parse req.body
24
75
 
25
76
  if res != nil
77
+
26
78
  if res.key?("confirmations")
79
+
27
80
  if res["confirmations"] > 5
81
+
28
82
  if res.key?("block_hash")
83
+
29
84
  if res.key?("confirmed")
30
- block_timestamp = DateTime.parse(res["confirmed"]).to_i
31
85
 
32
- op_return = self.getOpReturn(res)
86
+ block_timestamp = nil
87
+
88
+ begin
89
+
90
+ block_timestamp = DateTime.parse(res["confirmed"]).to_i
91
+
92
+ rescue => e
93
+ if @log.error?
94
+ @log.error("[Blockcypher.getTx] DateTime.parse('confirmed').to_i raised exception:")
95
+ @log.error("#{e.class}, #{e.message}")
96
+ @log.error("-> txid: #{txid}")
97
+ @log.error("--> url: #{url}")
98
+ end
99
+
100
+ raise e
101
+ end
102
+
103
+ if block_timestamp == nil
104
+ if @log.error?
105
+ @log.error("[Blockcypher.getTx] failed to convert 'confirmed' field to timestamp")
106
+ @log.error("-> txid: #{txid}")
107
+ @log.error("--> url: #{url}")
108
+ end
109
+
110
+ return nil
111
+ end
112
+
113
+ op_return = nil
114
+
115
+ begin
116
+
117
+ op_return = self.getOpReturn(res)
118
+
119
+ rescue => e
120
+ if @log.error?
121
+ @log.error("[Blockcypher.getTx] getOpReturn raised exception:")
122
+ @log.error("#{e.class}, #{e.message}")
123
+ @log.error("-> txid: #{txid}")
124
+ @log.error("--> res:")
125
+ @log.error(res)
126
+ end
127
+
128
+ raise e
129
+ end
33
130
 
34
131
  if op_return != nil
132
+
35
133
  prefix = op_return[0..2]
36
134
 
37
135
  if prefix == "VCH"
@@ -43,11 +141,62 @@ module VChainClient
43
141
  "block_timestamp" => block_timestamp,
44
142
  "op_return" => op_return
45
143
  }
144
+
145
+ else
146
+ if @log.error?
147
+ @log.error("[Blockcypher.getTx] wrong prefix '#{prefix}'")
148
+ @log.error("-> txid: #{txid}")
149
+ @log.error("--> res:")
150
+ @log.error(res)
151
+ end
46
152
  end
153
+
154
+ else
155
+ if @log.error?
156
+ @log.error("[Blockcypher.getTx] failed to get OP_RETURN")
157
+ @log.error("-> txid: #{txid}")
158
+ @log.error("--> res:")
159
+ @log.error(res)
160
+ end
47
161
  end
162
+
163
+ else
164
+ if @log.error?
165
+ @log.error("[Blockcypher.getTx] no 'confirmed' field in response")
166
+ @log.error("-> txid: #{txid}")
167
+ @log.error("--> url: #{url}")
168
+ end
48
169
  end
170
+
171
+ else
172
+ if @log.error?
173
+ @log.error("[Blockcypher.getTx] no 'block_hash' field in response")
174
+ @log.error("-> txid: #{txid}")
175
+ @log.error("--> url: #{url}")
176
+ end
49
177
  end
178
+
179
+ else
180
+ if @log.error?
181
+ @log.error("[Blockcypher.getTx] less than 6 confirmations")
182
+ @log.error("-> txid: #{txid}")
183
+ @log.error("--> url: #{url}")
184
+ end
50
185
  end
186
+
187
+ else
188
+ if @log.error?
189
+ @log.error("[Blockcypher.getTx] no 'confirmations' field")
190
+ @log.error("-> txid: #{txid}")
191
+ @log.error("--> url: #{url}")
192
+ end
193
+ end
194
+
195
+ else
196
+ if @log.error?
197
+ @log.error("[Blockcypher.getTx] REST call - empty response")
198
+ @log.error("-> txid: #{txid}")
199
+ @log.error("--> url: #{url}")
51
200
  end
52
201
  end
53
202