katapaty 0.3.1 → 0.3.2

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: 2add04e2fd5f93af3f4c04fdcfad01ac96255ea8
4
- data.tar.gz: ced506379dc1f7b9f624a5dd2def77738702bb9c
3
+ metadata.gz: dc8613cff7b2c9422344e372d3caf4f74a8a9147
4
+ data.tar.gz: b6448ed8b21e0ee7043c87fc68287799842b8c3f
5
5
  SHA512:
6
- metadata.gz: ddc86b97aa5d9b0106d72e6e717034f89b7737314dd9de21ee5848ff439ae214a0c16d84b057acc7eaa2e5fc1cfc243b4a02c680c1e6379dc69692386511efce
7
- data.tar.gz: 4b9a653cfb66b1a10f2878369d56cc5c0ee14e3a8d57a04b3c9f71a4416c589bb2843166647fee6cfe6298b0b7ec411364a46a899b6a3340665e3fd919e3677e
6
+ metadata.gz: c025e09a945d8295ddfb860f4c92b5198625bf61bbf0829e60dc2affc3f200068f1c9cdd5227e6e8f1220f52f87470be8c739eeedc96312d61bfb1bccecdd5ec
7
+ data.tar.gz: 4d772e3b257ab68524b8c74c285a4a7b98af921f9fbf30ffee11a40b4498fff89bd5eeaffdb39c2dccdc55068b855aabbc90b8b7b3f8b4a8303c9947aa1dac03
data/katapaty.gemspec CHANGED
@@ -24,6 +24,9 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "rake", "~> 10.0"
25
25
  spec.add_development_dependency "rspec", "~> 3.0"
26
26
 
27
- spec.add_dependency "json"
27
+ spec.add_dependency "json", "~> 2.1.0"
28
28
  spec.add_dependency "rest-client", "~> 1.8.0"
29
+ spec.add_dependency "bitcoin-ruby", "0.0.15"
30
+ spec.add_dependency "ruby-rc4", "~> 0.1.5"
31
+ spec.add_dependency "ffi", "~> 1.9.21"
29
32
  end
@@ -0,0 +1,121 @@
1
+ ##
2
+ # Author: https://github.com/brighton36/counterparty_ruby/blob/master/lib/counterparty/tx_decode.rb
3
+ # encoding: utf-8
4
+ # Inspriration heavily lifted from:
5
+ # - https://github.com/tokenly/counterparty-transaction-parser
6
+ ##
7
+ module Katapaty
8
+ class TxDecode
9
+ class UndefinedBehavior < StandardError; end
10
+ class InvalidOpReturn < StandardError; end
11
+ class InvalidOutput < StandardError; end
12
+ class MultisigUnsupported < StandardError; end
13
+
14
+ DEFAULT_PREFIX = 'CNTRPRTY'
15
+
16
+ OP_RETURN_PARTS = /^OP_RETURN ([a-z0-9]+)$/
17
+ P2PKH_PARTS = /^OP_DUP OP_HASH160 ([a-z0-9]+) OP_EQUALVERIFY OP_CHECKSIG$/
18
+ OP_MULTISIG_PARTS = /^[12] ([a-z0-9 ]+) ([23]) OP_CHECKMULTISIG$/
19
+
20
+ attr_accessor :sender_addr, :receiver_addr, :decrypt_key, :data, :prefix
21
+
22
+ def initialize(tx, options = {})
23
+ @prefix = options[:prefix] || DEFAULT_PREFIX
24
+ @decrypt_key = options[:decrypt_key] || [tx.inputs[0].prev_out.reverse_hth].pack('H*')
25
+
26
+ parse! (tx.respond_to? :outputs) ?
27
+ tx.outputs.collect{|out| out.parsed_script.to_string } : tx
28
+ end
29
+
30
+ def decrypt(chunk)
31
+ RC4.new(decrypt_key).decrypt chunk
32
+ end
33
+
34
+ private
35
+
36
+ def prefixed?(data, offset = 1)
37
+ data[offset...(prefix.length+offset)] == prefix
38
+ end
39
+
40
+ # This determines if the supplied operation is a non-data
41
+ def is_non_prefixed_p2pkh?(op)
42
+ P2PKH_PARTS.match(op) && !prefixed?(decrypt([$1].pack('H*')))
43
+ end
44
+
45
+ def hash160_from_p2pkh(op)
46
+ Bitcoin.hash160_to_address $1 if P2PKH_PARTS.match op
47
+ end
48
+
49
+ # Note that this isn't exactly the way counterparty parses the transactions.
50
+ # But , it reads cleaner, and worked on every transaction I could find.
51
+ # Mostly the difference is that the counterparty version is a loop that
52
+ # collects P2PKH's anywhere in the outputs, whereas this block takes a sender
53
+ # or receiver address from the top and bottom only
54
+ def parse!(outputs)
55
+ return if @data
56
+
57
+ # So typically, the first output is a P2PKH with the receiver address:
58
+ @receiver_addr = hash160_from_p2pkh outputs.shift if is_non_prefixed_p2pkh? outputs.first
59
+
60
+ # Parse the sender address:
61
+ @sender_addr = hash160_from_p2pkh outputs.pop if is_non_prefixed_p2pkh? outputs.last
62
+
63
+ @data = outputs.collect{|out|
64
+ # This weirdo line will send the regex matches to the operation handler
65
+ # that matches the line
66
+ send (case out
67
+ when OP_RETURN_PARTS then :data_from_opreturn
68
+ when P2PKH_PARTS then :data_from_opchecksig
69
+ when OP_MULTISIG_PARTS then :data_from_opcheckmultisig
70
+ else raise InvalidOutput
71
+ end), *$~.to_a[1..-1]
72
+ }.compact.join
73
+ end
74
+
75
+ def data_from_opreturn(data)
76
+ chunk = [data].pack('H*')
77
+
78
+ raise InvalidOpReturn if chunk.nil?
79
+
80
+ data = decrypt chunk
81
+
82
+ raise InvalidOpReturn unless prefixed?(data,0)
83
+
84
+ data[prefix.length..-1]
85
+ end
86
+
87
+ def data_from_opchecksig(pubkeyhash_text)
88
+ chunk = decrypt [pubkeyhash_text].pack('H*')
89
+
90
+ # This should get picked up by the sender and receiver pop/shift in parse!
91
+ # However, the counterparty lib would parse these obtuse addresses typically
92
+ # ATM - I can't find one in the wild
93
+ raise UndefinedBehavior unless prefixed? chunk
94
+
95
+ chunk_length = chunk[0].ord
96
+ chunk[(1+prefix.length)...chunk_length+1]
97
+ end
98
+
99
+ def data_from_opcheckmultisig(pubkeys_op, n_signatures_op)
100
+ pubkeys, n_signatures = pubkeys_op.split(' '), n_signatures_op.to_i
101
+
102
+ # There's no data in the last pubkey:
103
+ chunk = pubkeys[0...-1].collect{ |pubkey|
104
+ [pubkey].pack('H*')[1...-1] # Skip sign byte and nonce byte.
105
+ }.reduce(:+)
106
+
107
+ data = decrypt chunk
108
+
109
+ # Multisig transactions will break here. I haven't actually collected enough
110
+ # of these samples yet to really test, but it seems they are typically are
111
+ # at the top of the output stack:
112
+ raise MultisigUnsupported unless prefixed? data
113
+
114
+ # Padding byte in each output (instead of just in the last one) so that
115
+ # encoding methods may be mixed. Also, it’s just not very much data.
116
+ chunk_length = data[0].ord
117
+
118
+ data[1..chunk_length][prefix.length..-1]
119
+ end
120
+ end
121
+ end
@@ -1,3 +1,3 @@
1
1
  module Katapaty
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
data/lib/katapaty.rb CHANGED
@@ -4,6 +4,7 @@ require 'json'
4
4
  require 'katapaty/version'
5
5
  require 'katapaty/configuration'
6
6
  require 'katapaty/errors'
7
+ require 'katapaty/tx_decode'
7
8
 
8
9
  module Katapaty
9
10
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: katapaty
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - longhoang.wkm
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-02-05 00:00:00.000000000 Z
11
+ date: 2018-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -56,16 +56,16 @@ dependencies:
56
56
  name: json
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: 2.1.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: 2.1.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rest-client
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +80,48 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: 1.8.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: bitcoin-ruby
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '='
88
+ - !ruby/object:Gem::Version
89
+ version: 0.0.15
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '='
95
+ - !ruby/object:Gem::Version
96
+ version: 0.0.15
97
+ - !ruby/object:Gem::Dependency
98
+ name: ruby-rc4
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.1.5
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.1.5
111
+ - !ruby/object:Gem::Dependency
112
+ name: ffi
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 1.9.21
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 1.9.21
83
125
  description:
84
126
  email:
85
127
  - longhoang@wakumo.vn
@@ -100,6 +142,7 @@ files:
100
142
  - lib/katapaty.rb
101
143
  - lib/katapaty/configuration.rb
102
144
  - lib/katapaty/errors.rb
145
+ - lib/katapaty/tx_decode.rb
103
146
  - lib/katapaty/version.rb
104
147
  homepage: https://github.com/longhoangwkm/katapaty
105
148
  licenses: