coin-op 0.4.5 → 0.4.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: ddcac303efc3cea02f7d42a2a2a7a9c89d16c292
4
- data.tar.gz: 9a14fbb3178a73eeb5379fa486d6551c3c57835a
3
+ metadata.gz: daa2b1357a473f001974e80e34fcdd52358f906e
4
+ data.tar.gz: a0da314f07e56ad68d776de5234ddbbb8e49d4aa
5
5
  SHA512:
6
- metadata.gz: b7f368cf4336f909d61a54cad255936c9c8cc5b95bef6ffbdd6025df699b18d7bad1c6e25e2900a05a49df1586a2ed230260a5e1d9c8612d6dd52150ef9db041
7
- data.tar.gz: bc80f5346aa7d29608cb3d115188be258cf01e7b0d21b80b8a8d55a77a79fd636c44cd6d90b24ad9e070f25d1f2a3835af5901efcbe2b4ecb264a1937411cc87
6
+ metadata.gz: e076e686da9b9dc3a6212df1a21757317bd20792d4e9c342c6afaaa19d9acd41e60fb058f0e2b2859ea1ccf50b2f9a22c4ba2e4ac8e5945b42950be96b62c2ae
7
+ data.tar.gz: 4ff3f5c89ebb5d8e6ae0294904b9db02545bc3d2c1fe8b3598e20d293ebb518e86db9293170b609b862101fbc1865a831098a1cbb5f9d056d6e04d0ed7b0d3f6
@@ -1,3 +1,2 @@
1
- i��O��YI)1��p��E����W�4o�2����z�X�i�a,�Ga�Ӊ5� P���1��O۸� �Z��ҏ���U�n��7����i�˙��
2
- �~6,r� ��N��O&��}�ݶy���GPSk�ܸ��P�m`^˿�wwm�B�%?�3ǚ?N��Y�S�}�̮m��Nr Yҏt'�Hc[+gOT#%�l�����3�Q
3
- �h��U��
1
+ �.ˤ'-<��DmW
2
+ ��ɂ1 %�dvJQ/�$�1ſ��� ��.��@�nYC
data.tar.gz.sig CHANGED
Binary file
@@ -3,59 +3,76 @@ module CoinOp::Bit
3
3
 
4
4
  module Fee
5
5
 
6
+ # From http://bitcoinfees.com
7
+ AVG_P2PKH_BYTES = 148
8
+ AVG_OUTPUT_SIZE = 34
9
+
10
+ # From rough tests of Gem p2sh txs on 2015-09-08
11
+ AVG_P2SH_BYTES = 300
12
+
6
13
  module_function
7
14
 
8
15
  # Given an array of unspent Outputs and an array of Outputs for a
9
16
  # Transaction, estimate the fee required for the transaction to be
10
- # included in a block. Optionally takes an Integer specifying the
11
- # transaction size in bytes, which is necessary when using unspents
12
- # that deviate from the customary single signature.
17
+ # included in a block.
18
+ #
19
+ # Optionally takes an Integer tx_size specifying the transaction size in bytes
20
+ # This is useful if you have the scriptSigs for the unspents, because
21
+ # you can get a more accurate size than the estimate which is generated
22
+ # here by default
23
+ #
24
+ # Optionally takes an Integer fee_per_kb specifying the chosen cost per 1000
25
+ # bytes to use
13
26
  #
14
27
  # Returns the estimated fee in satoshis.
15
- def estimate(unspents, payees, tx_size=nil, network:)
28
+ def estimate(unspents, payees, network:, tx_size: nil, fee_per_kb: nil)
16
29
  # https://en.bitcoin.it/wiki/Transaction_fees
17
30
 
18
31
  # dupe because we'll need to add a change output
19
32
  payees = payees.dup
20
33
 
21
- unspent_total = unspents.inject(0) {|sum, output| sum += output.value}
22
- payee_total = payees.inject(0) {|sum, payee| sum += payee.value}
34
+ unspent_total = unspents.inject(0) { |sum, output| sum += output.value }
35
+ payee_total = payees.inject(0) { |sum, payee| sum += payee.value }
36
+
23
37
  nominal_change = unspent_total - payee_total
24
- payees << Output.new(value: nominal_change, network: network)
38
+ payees << Output.new(value: nominal_change, network: network) if nominal_change > 0
25
39
 
26
- tx_size ||= estimate_tx_size(unspents.size, payees.size)
27
- min = payees.min_by {|payee| payee.value }
40
+ tx_size ||= estimate_tx_size(unspents, payees)
28
41
 
42
+ # conditions for 0-fee transactions
29
43
  small = tx_size < 1000
30
- big_outputs = min.value > 1_000_000
31
44
 
32
- p = priority :size => tx_size, :unspents => (unspents.map do |output|
33
- {:value => output.value, :age => output.confirmations}
34
- end)
35
- high_priority = p > PRIORITY_THRESHOLD
45
+ min_payee = payees.min_by { |payee| payee.value }
46
+ big_outputs = min_payee.value > 1_000_000
47
+ high_priority = priority(
48
+ size: tx_size,
49
+ unspents: unspents.map { |output| { value: output.value, age: output.confirmations } }
50
+ ) > PRIORITY_THRESHOLD
36
51
 
37
- if small && big_outputs && high_priority
38
- 0
39
- else
40
- fee_for_bytes(tx_size, network: network)
41
- end
52
+ # 0-fee requirements met
53
+ return 0 if small && big_outputs && high_priority
42
54
 
55
+ # Otherwise, calculate the fee by size
56
+ fee_for_bytes(tx_size, network: network, fee_per_kb: fee_per_kb)
43
57
  end
44
58
 
45
- def fee_for_bytes(bytes, network:)
59
+ def fee_for_bytes(bytes, network:, fee_per_kb: nil)
46
60
  # https://en.bitcoin.it/wiki/Transaction_fees
47
61
  # > the reference implementation will round up the transaction size to the
48
62
  # > next thousand bytes and add a fee of 0.1 mBTC (0.0001 BTC) per thousand bytes
49
63
  size = (bytes / 1000) + 1
64
+ return size * fee_per_kb if fee_per_kb
50
65
  CoinOp.syncbit(network) { Bitcoin.network[:min_tx_fee] * size }
51
66
  end
52
67
 
53
- # From http://bitcoinfees.com. This estimation is only valid for
54
- # transactions with all inputs using the common "public key hash" method
55
- # for authorization.
56
- def estimate_tx_size(num_inputs, num_outputs)
57
- # From http://bitcoinfees.com.
58
- (148 * num_inputs) + (34 * num_outputs) + 10
68
+ def estimate_tx_size(inputs, outputs)
69
+ # tx overhead
70
+ 10 +
71
+ # outputs don't vary much in size
72
+ (AVG_OUTPUT_SIZE * outputs.size) +
73
+ # p2sh outputs are usually larger than p2pkh outputs, which don't vary much
74
+ inputs.inject(0) { |sum, input|
75
+ sum += input.script.type == :script_hash ? AVG_P2SH_BYTES : AVG_P2PKH_BYTES }
59
76
  end
60
77
 
61
78
 
@@ -10,8 +10,7 @@ module CoinOp::Bit
10
10
  transaction
11
11
  end
12
12
 
13
- # Construct a Transaction from a data structure of nested Hashes
14
- # and Arrays.
13
+ # Construct a Transaction from a data structure of nested Hashes and Arrays.
15
14
  def self.data(data, network:)
16
15
  version, lock_time, fee, inputs, outputs, confirmations =
17
16
  data.values_at :version, :lock_time, :fee, :inputs, :outputs, :confirmations
@@ -25,20 +24,17 @@ module CoinOp::Bit
25
24
  )
26
25
 
27
26
  outputs.each do |output_hash|
28
- transaction.add_output(Output.new(output_hash, network: network))
27
+ transaction.add_output(output_hash, network: network)
29
28
  end
30
29
 
31
30
  #FIXME: we're not handling sig_scripts for already signed inputs.
32
31
 
33
- if inputs
34
- # TODO: use #each instead of #each_with_index
35
- inputs.each_with_index do |input_hash, index|
36
- transaction.add_input(input_hash, network: network)
32
+ inputs.each do |input_hash|
33
+ transaction.add_input(input_hash, network: network)
37
34
 
38
- ## FIXME: verify that the supplied and computed sig_hashes match
39
- #puts :sig_hashes_match => (data[:sig_hash] == input.sig_hash)
40
- end
41
- end
35
+ ## FIXME: verify that the supplied and computed sig_hashes match
36
+ #puts :sig_hashes_match => (data[:sig_hash] == input.sig_hash)
37
+ end if inputs
42
38
 
43
39
  transaction
44
40
  end
@@ -160,17 +156,14 @@ module CoinOp::Bit
160
156
  # * an instance of Output
161
157
  # * a Hash describing an Output
162
158
  #
163
- def add_input(input, network:)
159
+ def add_input(input, network: @network)
164
160
  # TODO: allow specifying prev_tx and index with a Hash.
165
161
  # Possibly stop using SparseInput.
166
162
 
167
- unless input.is_a?(Input)
168
- input = Input.new input.merge(
169
- transaction: self,
170
- index: @inputs.size,
171
- network: network
172
- )
173
- end
163
+ input = Input.new(input.merge(transaction: self,
164
+ index: @inputs.size,
165
+ network: network)
166
+ ) unless input.is_a?(Input)
174
167
 
175
168
  @inputs << input
176
169
  self.update_native do |native|
@@ -180,15 +173,15 @@ module CoinOp::Bit
180
173
  end
181
174
 
182
175
  # Takes either an Output or a Hash describing an output.
183
- def add_output(output)
184
- unless output.is_a? Output
185
- output = Output.new(output, network: @network)
176
+ def add_output(output, network: @network)
177
+ if output.is_a?(Output)
178
+ output.set_transaction(self, @outputs.size)
179
+ else
180
+ output = Output.new(output.merge(transaction: self,
181
+ index: @outputs.size),
182
+ network: network)
186
183
  end
187
184
 
188
- index = @outputs.size
189
- # TODO: stop using set_transaction and just pass self to Output.new
190
- # Then remove output.set_transaction
191
- output.set_transaction self, index
192
185
  @outputs << output
193
186
  self.update_native do |native|
194
187
  native.add_out(output.native)
@@ -301,10 +294,11 @@ module CoinOp::Bit
301
294
  # Estimate the fee in satoshis for this transaction. Takes an optional
302
295
  # tx_size argument because it is impossible to determine programmatically
303
296
  # the size of the scripts used to create P2SH outputs.
304
- # Rough testing of the size of a 2of3 multisig p2sh input: 297
305
- def estimate_fee(tx_size=nil)
297
+ # Rough testing of the size of a 2of3 multisig p2sh input: 297 +/- 40 bytes
298
+ def estimate_fee(tx_size: nil, network: @network, fee_per_kb: nil)
306
299
  unspents = inputs.map(&:output)
307
- Fee.estimate(unspents, outputs, tx_size)
300
+ Fee.estimate(unspents, outputs,
301
+ network: network, tx_size: tx_size, fee_per_kb: fee_per_kb)
308
302
  end
309
303
 
310
304
  # Returns the transaction fee computed from the actual input and output
@@ -24,7 +24,7 @@ module CoinOp
24
24
 
25
25
  def int_to_byte_array(i, endianness: :little)
26
26
  arr = i.to_s(16).scan(/../).map { |x| x.hex.chr }
27
- if endianness = :little
27
+ if endianness == :little
28
28
  arr.reverse.join
29
29
  else
30
30
  arr.join
@@ -1,3 +1,3 @@
1
1
  module CoinOp
2
- VERSION = "0.4.5"
2
+ VERSION = "0.4.6"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coin-op
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew King
@@ -32,7 +32,7 @@ cert_chain:
32
32
  tdc4VS7IlSRxlZ3dBOgiigy9GXpJ+7F831AqjxL39EPwdr7RguTNz+pi//RKaT/U
33
33
  IlpVB+Xfk0vQdP7iYfjGxDzUf0FACMjsR95waJmadKW1Iy6STw2hwPhYIQz1Hu1A
34
34
  -----END CERTIFICATE-----
35
- date: 2015-08-07 00:00:00.000000000 Z
35
+ date: 2015-09-09 00:00:00.000000000 Z
36
36
  dependencies:
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: bitcoin-ruby
metadata.gz.sig CHANGED
Binary file