pochette 0.2.3 → 0.3.0

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: 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