txcatcher 0.1.100 → 0.2.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/VERSION +1 -1
- data/lib/txcatcher/bitcoin_rpc.rb +15 -0
- data/lib/txcatcher/models/transaction.rb +19 -17
- data/lib/txcatcher/server.rb +9 -2
- data/spec/models/transaction_spec.rb +2 -2
- data/txcatcher.gemspec +2 -2
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9bf1548d64396f39c3f5dd29ce44c08db1cf0a8b7a561621964d93157afb2736
|
4
|
+
data.tar.gz: c84ec5f6b8c02b5edc5c37bc53550079ad80ff899778959d59b7162f8bedd62b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c753e7883e49dbd218424f43e3edde6431bbec2a9d3817991424933c38515f27c118bfd65ac7778a725ed08a0becb6e93a6ee7330ecf0b7fa607f9c397d4f25a
|
7
|
+
data.tar.gz: 4bba3d57d20cddad92b8221984df9d8913e46cbbbda3db744529e5e4f577a8327e99b390d5c8a94ed60b3691070562d71478f41666284d20e68d36d2e89985de
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
@@ -27,6 +27,21 @@ class BitcoinRPC
|
|
27
27
|
http.request(request).body
|
28
28
|
end
|
29
29
|
|
30
|
+
def get_block_transactions(block_height)
|
31
|
+
TxCatcher::LOGGER.report "--- checking transactions in block #{block_height}"
|
32
|
+
block_hash = self.getblockhash(block_height)
|
33
|
+
TxCatcher.rpc_node.getblock(block_hash)
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_blocks(limit=100)
|
37
|
+
blocks = []
|
38
|
+
limit.times do |i|
|
39
|
+
height = TxCatcher.current_block_height - i
|
40
|
+
blocks << get_block_transactions(height)
|
41
|
+
end
|
42
|
+
blocks
|
43
|
+
end
|
44
|
+
|
30
45
|
class JSONRPCError < RuntimeError
|
31
46
|
attr_accessor :data
|
32
47
|
def initialize(data)
|
@@ -44,33 +44,35 @@ module TxCatcher
|
|
44
44
|
|
45
45
|
# Queries rpc node to check whether the transaction has been included in any of the blocks,
|
46
46
|
# but only if current block_height is nil.
|
47
|
-
def update_block_height!(
|
48
|
-
|
49
|
-
# This calculates the approximate number of blocks to check.
|
50
|
-
# So, for example, if transaction is less than 10 minutes old,
|
51
|
-
# there's probably no reason to try and check more than 2-3 blocks back.
|
52
|
-
# However, to make absolute sure, we always bump up this number for 10 blocks.
|
53
|
-
# Over larger periods of time, the avg block per minute value should even out, so
|
54
|
-
# it's probably going to be fine either way.
|
55
|
-
created_minutes_ago = ((self.created_at - Time.now).to_i/60)
|
56
|
-
blocks_to_check = (created_minutes_ago / 10).abs + 10
|
47
|
+
def update_block_height!(dont_save: false, blocks: nil)
|
57
48
|
return self.block_height if self.block_height
|
58
|
-
|
49
|
+
blocks = TxCatcher.rpc_node.get_blocks(blocks_to_check_for_inclusion_if_unconfirmed) unless blocks
|
59
50
|
|
60
|
-
|
61
|
-
while i <= blocks_to_check
|
62
|
-
block_hash = TxCatcher.rpc_node.getblockhash(TxCatcher.current_block_height - i)
|
63
|
-
block = TxCatcher.rpc_node.getblock(block_hash)
|
64
|
-
i += 1
|
65
|
-
LOGGER.report "--- checking block #{TxCatcher.current_block_height - i} for tx #{self.txid}"
|
51
|
+
for block in blocks do
|
66
52
|
if block["tx"] && block["tx"].include?(self.txid)
|
67
53
|
LOGGER.report "tx #{self.txid} block height updated to #{block["height"]}"
|
68
54
|
self.update(block_height: block["height"]) if !dont_save
|
69
55
|
return block["height"].to_i
|
56
|
+
else
|
57
|
+
return nil
|
70
58
|
end
|
71
59
|
end
|
72
60
|
end
|
73
61
|
|
62
|
+
# This calculates the approximate number of blocks to check.
|
63
|
+
# So, for example, if transaction is less than 10 minutes old,
|
64
|
+
# there's probably no reason to try and check more than 2-3 blocks back.
|
65
|
+
# However, to make absolute sure, we always bump up this number by 10 blocks.
|
66
|
+
# Over larger periods of time, the avg block per minute value should even out, so
|
67
|
+
# it's probably going to be fine either way.
|
68
|
+
def blocks_to_check_for_inclusion_if_unconfirmed(limit=100)
|
69
|
+
return false if self.block_height
|
70
|
+
created_minutes_ago = ((self.created_at - Time.now).to_i/60)
|
71
|
+
blocks_to_check = (created_minutes_ago / 10).abs + 10
|
72
|
+
blocks_to_check = limit if blocks_to_check > limit
|
73
|
+
blocks_to_check
|
74
|
+
end
|
75
|
+
|
74
76
|
private
|
75
77
|
|
76
78
|
def parse_transaction
|
data/lib/txcatcher/server.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'ruby-prof'
|
1
2
|
module TxCatcher
|
2
3
|
|
3
4
|
class Server < Goliath::API
|
@@ -9,9 +10,12 @@ module TxCatcher
|
|
9
10
|
begin
|
10
11
|
return route_for(uri)
|
11
12
|
rescue BitcoinRPC::JSONRPCError => e
|
13
|
+
puts e.to_s
|
14
|
+
puts e.backtrace.join("\n")
|
12
15
|
return [400, {}, { error: e.data }.to_json]
|
13
16
|
rescue Exception => e
|
14
|
-
|
17
|
+
puts e.to_s
|
18
|
+
puts e.backtrace.join("\n")
|
15
19
|
return [500, {}, { error: e.to_s }.to_json]
|
16
20
|
end
|
17
21
|
end
|
@@ -72,6 +76,7 @@ module TxCatcher
|
|
72
76
|
newly_confirmed_txs_to_update = []
|
73
77
|
|
74
78
|
transactions = model.deposits.map { |d| d.transaction }
|
79
|
+
transactions.sort! { |t1,t2| t2.created_at <=> t1.created_at }
|
75
80
|
utxos = transactions.map do |t|
|
76
81
|
outs = t.tx_hash["vout"].select { |out| out["scriptPubKey"]["addresses"] == [addr] }
|
77
82
|
outs.map! do |out|
|
@@ -84,8 +89,10 @@ module TxCatcher
|
|
84
89
|
outs
|
85
90
|
end.flatten
|
86
91
|
|
92
|
+
blocks = TxCatcher.rpc_node.get_blocks(unconfirmed_txs_to_update.first.blocks_to_check_for_inclusion_if_unconfirmed)
|
93
|
+
|
87
94
|
unconfirmed_txs_to_update = unconfirmed_txs_to_update.map do |t|
|
88
|
-
tx_block_height = t.update_block_height!(
|
95
|
+
tx_block_height = t.update_block_height!(dont_save: true, blocks: blocks)
|
89
96
|
if tx_block_height && tx_block_height > 0
|
90
97
|
newly_confirmed_txs_to_update << t
|
91
98
|
nil
|
@@ -27,8 +27,8 @@ RSpec.describe TxCatcher::Transaction do
|
|
27
27
|
end
|
28
28
|
|
29
29
|
it "updates block height by making manual requests to RPC and searching if tx is included in one of the previous blocks" do
|
30
|
-
expect(TxCatcher.rpc_node).to receive(:getblockhash).and_return("blockhash123")
|
31
|
-
expect(TxCatcher.rpc_node).to receive(:getblock).and_return({ "height" => "123", "tx" => [@transaction.txid], "hash" => "blockhash123"})
|
30
|
+
expect(TxCatcher.rpc_node).to receive(:getblockhash).exactly(10).times.and_return("blockhash123")
|
31
|
+
expect(TxCatcher.rpc_node).to receive(:getblock).exactly(10).times.and_return({ "height" => "123", "tx" => [@transaction.txid], "hash" => "blockhash123"})
|
32
32
|
@transaction.update_block_height!
|
33
33
|
expect(@transaction.block_height).to eq(123)
|
34
34
|
end
|
data/txcatcher.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: txcatcher 0.
|
5
|
+
# stub: txcatcher 0.2.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "txcatcher".freeze
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.2.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|