pochette 0.2.3 → 0.3.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: c67a840f37e1c8a8e29560276521c6a10a2edfe6
4
- data.tar.gz: 5b38f917803fb98e70387de1db5753c505b3c03a
3
+ metadata.gz: d61a337d84f849c127e76e2d06db768306d3d050
4
+ data.tar.gz: 8ab1cb06f94a3bc4f88c0e641094ec8f54474d5a
5
5
  SHA512:
6
- metadata.gz: 2e91fae50ed18c182a165e8020e71be01b630baa81b89d0c1f0644e91a661b743cc44a9dbe80ed7e65a599745b07504e56551586747d90d6dc1748fa73f3af05
7
- data.tar.gz: baabb89ac0dde0290553376df3ebfa818454791496854050e292ec6684d80da120ca29666a306d695076fafb582d592296dac2fc1d4a95c0914ba1d66f8586b8
6
+ metadata.gz: 466b1a81cb4f6a2a5e302d613ddd0ddb994edc1312dc3c6d7a6bf6bcee6487956146e8645a6a0a8471b97a169daa4df9727ba7e31cf992d73ffb6d4f00c25aca
7
+ data.tar.gz: 54a663b538f938b1a2efc86f0d9ac46f95c454a783611b01152a3165bc4db2d01f4dcfe117a63878ddddda7caf035896ca2378f61ea9bf008a82804baa540e3f
data/README.md CHANGED
@@ -291,7 +291,6 @@ A hash with
291
291
  depth: 0,
292
292
  child_num: 0,
293
293
  fingerprint: 0,
294
- path: [],
295
294
  public_key: '03142b0a6fa6943e7276ddc42582c6b169243d289ff17e7c8101797047eed90c9b',
296
295
  }
297
296
  },
@@ -301,7 +300,6 @@ A hash with
301
300
  depth: 0,
302
301
  child_num: 0,
303
302
  fingerprint: 0,
304
- path: [],
305
303
  public_key: '027565ceb190647ec5c566805ebc5cb6166ae2ee1d4995495f61b9eff371ec0e61',
306
304
  }
307
305
  },
@@ -311,7 +309,6 @@ A hash with
311
309
  depth: 0,
312
310
  child_num: 0,
313
311
  fingerprint: 0,
314
- path: [],
315
312
  public_key: '028776ff18f0f3808d6d42749a6e2baee5c75c3f7ae07445403a3a5690d580a0af',
316
313
  }
317
314
  }
@@ -30,8 +30,12 @@ module Pochette
30
30
 
31
31
  module Backends
32
32
  end
33
+
34
+ class InvalidSignatureError < StandardError
35
+ end
33
36
  end
34
37
 
38
+ require "pochette/backends/base"
35
39
  require "pochette/backends/bitcoin_core"
36
40
  require "pochette/backends/blockchain_info"
37
41
  require "pochette/backends/trendy"
@@ -0,0 +1,88 @@
1
+ # All Pochette backends must conform to this interface.
2
+ class Pochette::Backends::Base
3
+ # Lists all bitcoins received by a list of addresses
4
+ # after a given date. Includes both confirmed and unconfirmed
5
+ # transactions, unconfirmed transactions have a nil block height.
6
+ # Returns a list of lists as following:
7
+ # amount: Amount received (in satoshis)
8
+ # address: Public address receiving the amount.
9
+ # txid: The hash for the transaction that received it.
10
+ # confirmations: Transaction confirmations
11
+ # output position: To disambiguate in case address received more than once.
12
+ # sender addresses: Comma separated list of input addresses,
13
+ # used to identify deposits from trusted parties.
14
+ # can be used to identify deposits from trusted parties.
15
+ def incoming_for(addresses, min_date)
16
+ raise NotImplementedError
17
+ end
18
+
19
+ # Gets the total received, spent and balance for
20
+ # a list of addresses. Confirmed balances are enforced to have a number
21
+ # of confirmation, appearing in a block is not enough.
22
+ # Returns a hash with:
23
+ # { address: [received, sent, total,
24
+ # unconfirmed_received, unconfirmed_sent, unconfirmed_total],
25
+ # ...}
26
+ def balances_for(addresses, confirmations)
27
+ raise NotImplementedError
28
+ end
29
+
30
+ # Get unspent utxos for the given addresses,
31
+ # returns a list of lists like so:
32
+ # [[address, txid, position (vout), amount (in satoshis)], ...]
33
+ def list_unspent(addresses)
34
+ raise NotImplementedError
35
+ end
36
+
37
+ # Gets information for the given transactions
38
+ # returns a list of objects, like so:
39
+ # [
40
+ # { hash: txid,
41
+ # version: 1,
42
+ # lock_time: 0,
43
+ # inputs: [
44
+ # { prev_hash: txid,
45
+ # prev_index: 0,
46
+ # sequence: 0,
47
+ # script_sig: hex_signature
48
+ # },
49
+ # ...
50
+ # ],
51
+ # bin_outputs: [
52
+ # { amount: amount (as satoshis),
53
+ # script_pubkey: hex_script
54
+ # },
55
+ # ...
56
+ # ]
57
+ # }
58
+ def list_transactions(txids)
59
+ raise NotImplementedError
60
+ end
61
+
62
+ def pushtx(hex, options = { })
63
+ verify_signatures(hex, options) if options[:verify_signatures]
64
+ propagate(hex)
65
+ Bitcoin::Protocol::Tx.new(hex.htb).hash
66
+ end
67
+
68
+ def propagate(hex)
69
+ raise NotImplementedError
70
+ end
71
+
72
+ def block_height
73
+ raise NotImplementedError
74
+ end
75
+
76
+ def verify_signatures(hex, options = { })
77
+ tx = Bitcoin::P::Tx.new(hex.htb)
78
+ tx.inputs.each_with_index do |input, idx|
79
+ prev_tx = list_transactions([ input.previous_output ]).first
80
+ outputs = prev_tx[:bin_outputs]
81
+ script_pubkey = outputs[input.prev_out_index][:script_pubkey].htb
82
+ unless tx.verify_input_signature(idx, script_pubkey, Time.now.to_i, options)
83
+ raise Pochette::InvalidSignatureError, "Signature for input #{idx} is invalid."
84
+ end
85
+ end
86
+ true
87
+ end
88
+ end
@@ -1,7 +1,7 @@
1
1
  # A bitcoin backend that uses bitcoin-core to retrieve information.
2
2
  # See Pochette::Backends::Trendy to learn more about the backend
3
3
  # interface and contract.
4
- class Pochette::Backends::BitcoinCore
4
+ class Pochette::Backends::BitcoinCore < Pochette::Backends::Base
5
5
  def initialize(rpc_url)
6
6
  @rpc_url = rpc_url
7
7
  end
@@ -103,7 +103,7 @@ class Pochette::Backends::BitcoinCore
103
103
  client.getinfo[:blocks]
104
104
  end
105
105
 
106
- def pushtx(hex)
106
+ def propagate(hex)
107
107
  client.sendrawtransaction(hex)
108
108
  end
109
109
  end
@@ -3,7 +3,7 @@
3
3
  # interface and contract.
4
4
  require 'open-uri'
5
5
 
6
- class Pochette::Backends::BlockchainInfo
6
+ class Pochette::Backends::BlockchainInfo < Pochette::Backends::Base
7
7
  cattr_accessor(:cooldown){1}
8
8
  attr_accessor :api_key
9
9
 
@@ -17,6 +17,13 @@ class Pochette::Backends::BlockchainInfo
17
17
  address = Bitcoin::Script.new(utxo['script'].htb).get_address
18
18
  [address, utxo['tx_hash_big_endian'], utxo['tx_output_n'].to_i, utxo['value'], utxo['script']]
19
19
  end
20
+ rescue OpenURI::HTTPError => e
21
+ # Blockchain.info returns 500 when there are no unspent outputs
22
+ if e.io.read == "No free outputs to spend"
23
+ return []
24
+ else
25
+ raise
26
+ end
20
27
  end
21
28
 
22
29
  def balances_for(addresses, confirmations)
@@ -85,13 +92,12 @@ class Pochette::Backends::BlockchainInfo
85
92
  get_json("latestblock", {format: 'json'})['height'].to_i
86
93
  end
87
94
 
88
- def pushtx(hex)
95
+ def propagate(hex)
89
96
  uri = URI.parse("https://blockchain.info/pushtx")
90
97
  params = { "tx" => hex }
91
98
  params['api_code'] = api_key if api_key
92
99
  response = Net::HTTP.post_form(uri, params)
93
100
  raise StandardError.new(response) if response.code.to_i != 200
94
- Bitcoin::Protocol::Tx.new(hex.htb).hash
95
101
  end
96
102
 
97
103
  def get_json(path, params={})
@@ -2,87 +2,12 @@
2
2
  # to list unspent outputs, incoming payments, etcetera.
3
3
  # It chooses the backend to use based on its latest block, trying
4
4
  # to always use the most up to date one.
5
- # Its public instance methods are the contract to be used by any
6
- # other backend, all Pochette backends must define
7
- # thes public methods (Except for the initializer).
8
- class Pochette::Backends::Trendy
5
+ class Pochette::Backends::Trendy < Pochette::Backends::Base
9
6
  def initialize(backends)
10
7
  @backends = backends
11
8
  end
12
-
13
- # Lists all bitcoins received by a list of addresses
14
- # after a given date. Includes both confirmed and unconfirmed
15
- # transactions, unconfirmed transactions have a nil block height.
16
- # Returns a list of lists as following:
17
- # amount: Amount received (in satoshis)
18
- # address: Public address receiving the amount.
19
- # txid: The hash for the transaction that received it.
20
- # confirmations: Transaction confirmations
21
- # output position: To disambiguate in case address received more than once.
22
- # sender addresses: Comma separated list of input addresses,
23
- # used to identify deposits from trusted parties.
24
- # can be used to identify deposits from trusted parties.
25
- def incoming_for(addresses, min_date)
26
- backend.incoming_for(addresses, min_date)
27
- end
28
-
29
- # Gets the total received, spent and balance for
30
- # a list of addresses. Confirmed balances are enforced to have a number
31
- # of confirmation, appearing in a block is not enough.
32
- # Returns a hash with:
33
- # { address: [received, sent, total,
34
- # unconfirmed_received, unconfirmed_sent, unconfirmed_total],
35
- # ...}
36
- def balances_for(addresses, confirmations)
37
- backend.balances_for(addresses, confirmations)
38
- end
39
9
 
40
- # Get unspent utxos for the given addresses,
41
- # returns a list of lists like so:
42
- # [[address, txid, position (vout), amount (in satoshis)], ...]
43
- def list_unspent(addresses)
44
- backend.list_unspent(addresses)
45
- rescue OpenURI::HTTPError => e
46
- # Blockchain.info returns 500 when there are no unspent outputs
47
- if e.io.read == "No free outputs to spend"
48
- return []
49
- else
50
- raise
51
- end
52
- end
53
-
54
- # Gets information for the given transactions
55
- # returns a list of objects, like so:
56
- # [
57
- # { hash: txid,
58
- # version: 1,
59
- # lock_time: 0,
60
- # inputs: [
61
- # { prev_hash: txid,
62
- # prev_index: 0,
63
- # sequence: 0,
64
- # script_sig: hex_signature
65
- # },
66
- # ...
67
- # ],
68
- # bin_outputs: [
69
- # { amount: amount (as satoshis),
70
- # script_pubkey: hex_script
71
- # },
72
- # ...
73
- # ]
74
- # }
75
- def list_transactions(txids)
76
- backend.list_transactions(txids)
77
- end
78
-
79
- def pushtx(hex)
80
- backend.pushtx(hex)
81
- end
82
-
83
- def block_height
84
- backend.block_height
85
- end
10
+ delegate :incoming_for, :balances_for, :list_unspent, :list_transactions, :pushtx, :block_height, to: :backend
86
11
 
87
12
  protected
88
13
 
@@ -104,7 +104,6 @@ protected
104
104
  depth: 0,
105
105
  child_num: 0,
106
106
  fingerprint: 0,
107
- path: [],
108
107
  public_key: node.public_key.key,
109
108
  }
110
109
  }
@@ -1,3 +1,3 @@
1
1
  module Pochette
2
- VERSION = "0.2.3"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pochette
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nubis
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-12-18 00:00:00.000000000 Z
12
+ date: 2016-10-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -173,6 +173,7 @@ files:
173
173
  - bin/console
174
174
  - bin/setup
175
175
  - lib/pochette.rb
176
+ - lib/pochette/backends/base.rb
176
177
  - lib/pochette/backends/bitcoin_core.rb
177
178
  - lib/pochette/backends/blockchain_info.rb
178
179
  - lib/pochette/backends/trendy.rb