coin-op 0.4.5 → 0.4.6
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
- checksums.yaml.gz.sig +2 -3
- data.tar.gz.sig +0 -0
- data/lib/coin-op/bit/fee.rb +43 -26
- data/lib/coin-op/bit/transaction.rb +23 -29
- data/lib/coin-op/encodings.rb +1 -1
- data/lib/coin-op/version.rb +1 -1
- metadata +2 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: daa2b1357a473f001974e80e34fcdd52358f906e
|
4
|
+
data.tar.gz: a0da314f07e56ad68d776de5234ddbbb8e49d4aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e076e686da9b9dc3a6212df1a21757317bd20792d4e9c342c6afaaa19d9acd41e60fb058f0e2b2859ea1ccf50b2f9a22c4ba2e4ac8e5945b42950be96b62c2ae
|
7
|
+
data.tar.gz: 4ff3f5c89ebb5d8e6ae0294904b9db02545bc3d2c1fe8b3598e20d293ebb518e86db9293170b609b862101fbc1865a831098a1cbb5f9d056d6e04d0ed7b0d3f6
|
checksums.yaml.gz.sig
CHANGED
@@ -1,3 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
�h��U��
|
1
|
+
�.ˤ'-<��DmW
|
2
|
+
��ɂ1 %�dvJQ/�$�1ſ��� ��.��@�nY�C
|
data.tar.gz.sig
CHANGED
Binary file
|
data/lib/coin-op/bit/fee.rb
CHANGED
@@ -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.
|
11
|
-
#
|
12
|
-
#
|
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
|
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
|
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
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
-
|
38
|
-
|
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
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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(
|
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
|
-
|
34
|
-
|
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
|
-
|
39
|
-
|
40
|
-
|
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
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
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
|
-
|
185
|
-
output
|
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
|
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,
|
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
|
data/lib/coin-op/encodings.rb
CHANGED
data/lib/coin-op/version.rb
CHANGED
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.
|
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-
|
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
|