sibit 0.30.4 → 0.30.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d3d770048c5c19650ec325dd100d556c798c58d27ae06c120569161dc5ede087
4
- data.tar.gz: b8b19fa66905fcd77379c4ebe6892ed6e5ee7ceece7ae1cc46f8921a50bb8a0e
3
+ metadata.gz: aa32d663437f956373254dfd5ee62d072a984a7848ef455d26d22727293199ef
4
+ data.tar.gz: 6a0464cb926cce844ec89e380352c9d0e94c97ffbd26a9609ecbcefd82ee9413
5
5
  SHA512:
6
- metadata.gz: eb8af223383b416274d70182ab890d8d41540687112086510827f5b95f0a3ced72bd641d57fb7afd4bb43ff6c0ece6eb453dba8d4ff91f61d7097e069370f716
7
- data.tar.gz: 2ec794eb825e11f3154c28f874e1fa6e6aadbe5be70510576a6c45768f5afba653561e1ade8e32ce3f8d1e32b64ea4b610892ec2a557b1504d377961358769b8
6
+ metadata.gz: 3711ea50589117bc03497b111c11f7509b7be90dd8656aa7938ae3a72e730a8f13b74a1706589ca224b883dfa2223875f9e5aa204865e58d7856dcfd28a6fd17
7
+ data.tar.gz: 8ed48713e2795903a90501fed8da5a48dda43d62c9e8a152e4200003cf4ca51903fc53d745068de5502faadedf69d76d99b3024742b7d0a164924df62d3796f4
data/Gemfile CHANGED
@@ -10,6 +10,7 @@ gemspec
10
10
 
11
11
  gem 'aruba', '~>2.2', require: false
12
12
  gem 'cucumber', '~>10.0', require: false
13
+ gem 'donce', '~>0.2', require: false
13
14
  gem 'logger', '~>1.7', require: false
14
15
  gem 'minitest', '~>6.0', require: false
15
16
  gem 'minitest-reporters', '~>1.7', require: false
data/Gemfile.lock CHANGED
@@ -62,6 +62,10 @@ GEM
62
62
  decoor (0.1.0)
63
63
  diff-lcs (1.6.2)
64
64
  docile (1.4.1)
65
+ donce (0.2.4)
66
+ backtrace (~> 0.3)
67
+ os (~> 1.1)
68
+ qbash (~> 0.3)
65
69
  elapsed (0.2.1)
66
70
  loog (~> 0.6)
67
71
  tago (~> 0.1)
@@ -78,6 +82,7 @@ GEM
78
82
  logger (~> 1.0)
79
83
  memoist3 (1.0.0)
80
84
  mini_mime (1.1.5)
85
+ mini_portile2 (2.8.9)
81
86
  minitest (6.0.1)
82
87
  prism (~> 1.5)
83
88
  minitest-reporters (1.7.1)
@@ -86,9 +91,8 @@ GEM
86
91
  minitest (>= 5.0)
87
92
  ruby-progressbar
88
93
  multi_test (1.1.0)
89
- nokogiri (1.18.10-arm64-darwin)
90
- racc (~> 1.4)
91
- nokogiri (1.18.10-x86_64-linux-gnu)
94
+ nokogiri (1.18.10)
95
+ mini_portile2 (~> 2.8.2)
92
96
  racc (~> 1.4)
93
97
  openssl (3.3.2)
94
98
  os (1.1.4)
@@ -182,6 +186,7 @@ PLATFORMS
182
186
  DEPENDENCIES
183
187
  aruba (~> 2.2)
184
188
  cucumber (~> 10.0)
189
+ donce (~> 0.2)
185
190
  logger (~> 1.7)
186
191
  minitest (~> 6.0)
187
192
  minitest-reporters (~> 1.7)
data/README.md CHANGED
@@ -63,15 +63,18 @@ $ sibit pay AMOUNT FEE P1,P2,... TARGET CHANGE
63
63
  e87f138c9ebf5986151667719825c28458a28cc66f69fed4f1032a93b399fdf8
64
64
  ```
65
65
 
66
- Here,
67
- `AMOUNT` is the amount of [satoshi] you are sending,
68
- `FEE` is the [miner fee] you are ready to spend to get
66
+ Here:
67
+
68
+ * `AMOUNT` is the amount of [satoshi] you are sending (integer),
69
+ or `0.42BTC` if in bitcoins (with a suffix),
70
+ * `FEE` is the [miner fee] you are ready to spend to get
69
71
  this transaction delivered (you can say `S`, `M`, `L`, or `XL` if you want it
70
72
  to be calculated automatically),
71
- `P1,P2,...` is a comma-separated list
73
+ * `P1,P2,...` is a comma-separated list
72
74
  of private keys `P` you are sending your coins from,
73
- `TARGET` is the address you are sending to,
74
- `CHANGE` is the address where the change goes.
75
+ * `TARGET` is the address you are sending to,
76
+ * `CHANGE` is the address where the change goes.
77
+
75
78
  The transaction hash is returned.
76
79
  Not all [UTXOs] may be used, but only the necessary amount of them.
77
80
 
data/lib/sibit/key.rb CHANGED
@@ -21,6 +21,8 @@ class Sibit
21
21
  MIN_PRIV = 0x01
22
22
  MAX_PRIV = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140
23
23
 
24
+ attr_reader :network
25
+
24
26
  def self.generate
25
27
  key = OpenSSL::PKey::EC.generate('secp256k1')
26
28
  pvt = key.private_key.to_s(16).rjust(64, '0').downcase
@@ -28,9 +30,10 @@ class Sibit
28
30
  end
29
31
 
30
32
  def initialize(privkey)
31
- @privkey = privkey
33
+ @network = :mainnet
32
34
  @compressed = true
33
- @key = build(privkey)
35
+ @privkey = decode(privkey)
36
+ @key = build(@privkey)
34
37
  end
35
38
 
36
39
  def priv
@@ -44,17 +47,18 @@ class Sibit
44
47
 
45
48
  def addr
46
49
  hash = hash160(pub)
47
- versioned = "00#{hash}"
50
+ prefix = @network == :mainnet ? '00' : '6f'
51
+ versioned = "#{prefix}#{hash}"
48
52
  checksum = Base58.new(versioned).check
49
53
  Base58.new(versioned + checksum).encode
50
54
  end
51
55
 
52
56
  def sign(data)
53
- @key.sign('SHA256', data)
57
+ @key.dsa_sign_asn1(data)
54
58
  end
55
59
 
56
60
  def verify(data, sig)
57
- @key.verify('SHA256', sig, data)
61
+ @key.dsa_verify_asn1(data, sig)
58
62
  rescue OpenSSL::PKey::PKeyError
59
63
  false
60
64
  end
@@ -82,5 +86,15 @@ class Sibit
82
86
  bytes = [hex].pack('H*')
83
87
  Digest::RMD160.hexdigest(Digest::SHA256.digest(bytes))
84
88
  end
89
+
90
+ def decode(key)
91
+ return key if key.length == 64 && key.match?(/\A[0-9a-f]+\z/i)
92
+ raw = Base58.new(key).decode
93
+ version = raw[0, 2]
94
+ @network = version == '80' ? :mainnet : :testnet
95
+ body = raw[2..-9]
96
+ @compressed = body.length == 66 && body.end_with?('01')
97
+ @compressed ? body[0, 64] : body
98
+ end
85
99
  end
86
100
  end
data/lib/sibit/script.rb CHANGED
@@ -25,8 +25,8 @@ class Sibit
25
25
  @bytes = [hex].pack('H*').bytes
26
26
  end
27
27
 
28
- def address
29
- return p2pkh_address if p2pkh?
28
+ def address(network = :mainnet)
29
+ return p2pkh_address(network) if p2pkh?
30
30
  nil
31
31
  end
32
32
 
@@ -46,10 +46,11 @@ class Sibit
46
46
 
47
47
  private
48
48
 
49
- def p2pkh_address
49
+ def p2pkh_address(network)
50
50
  h = hash160
51
51
  return nil unless h
52
- versioned = "00#{h}"
52
+ prefix = network == :mainnet ? '00' : '6f'
53
+ versioned = "#{prefix}#{h}"
53
54
  checksum = Base58.new(versioned).check
54
55
  Base58.new(versioned + checksum).encode
55
56
  end
data/lib/sibit/version.rb CHANGED
@@ -9,5 +9,5 @@
9
9
  # License:: MIT
10
10
  class Sibit
11
11
  # Current version of the library.
12
- VERSION = '0.30.4' unless defined?(VERSION)
12
+ VERSION = '0.30.6' unless defined?(VERSION)
13
13
  end
data/lib/sibit.rb CHANGED
@@ -18,7 +18,7 @@ require_relative 'sibit/version'
18
18
  # Copyright:: Copyright (c) 2019-2025 Yegor Bugayenko
19
19
  # License:: MIT
20
20
  class Sibit
21
- # Minimium fee we must pay for transaction processing:
21
+ # Minimum fee we must pay for transaction processing:
22
22
  MIN_SATOSHI_PER_BYTE = 0.1
23
23
 
24
24
  # Constructor.
@@ -103,7 +103,9 @@ class Sibit
103
103
  # +change+: the address where the change has to be sent to
104
104
  def pay(amount, fee, sources, target, change, skip_utxo: [])
105
105
  p = price('USD')
106
- sources = sources.to_h { |k| [Key.new(k).addr, k] }
106
+ keys = sources.map { |k| Key.new(k) }
107
+ network = keys.first&.network || :mainnet
108
+ sources = keys.to_h { |k| [k.addr, k.priv] }
107
109
  satoshi = satoshi(amount)
108
110
  builder = TxBuilder.new
109
111
  unspent = 0
@@ -116,12 +118,16 @@ class Sibit
116
118
  @log.debug("UTXO skipped: #{utxo[:hash]}")
117
119
  next
118
120
  end
121
+ unless utxo[:confirmations]&.positive?
122
+ @log.debug("UTXO with no confirmations: #{utxo[:hash]}")
123
+ next
124
+ end
119
125
  unspent += utxo[:value]
120
126
  builder.input do |i|
121
127
  i.prev_out(utxo[:hash])
122
128
  i.prev_out_index(utxo[:index])
123
129
  i.prev_out_script = script_hex(utxo[:script])
124
- address = Script.new(script_hex(utxo[:script])).address
130
+ address = Script.new(script_hex(utxo[:script])).address(network)
125
131
  k = sources[address]
126
132
  raise Error, "UTXO arrived to #{address} is incorrect" unless k
127
133
  i.signature_key(key(k))
@@ -155,7 +161,7 @@ class Sibit
155
161
  #{tx.inputs.map { |i| " in: #{i.prev_out.unpack1('H*')}:#{i.prev_out_index}" }.join("\n ")}
156
162
  #{tx.out.count} output#{'s' if tx.out.count > 1}:
157
163
  #{tx.outputs.map { |o| "out: #{o.script_hex} / #{num(o.value, p)}" }.join("\n ")}
158
- Min fee: #{num(MIN_SATOSHI_PER_BYTE, p)} s/byte
164
+ Min fee: #{num(MIN_SATOSHI_PER_BYTE, p)} /byte
159
165
  Fee requested: #{num(f, p)} as \"#{fee}\"
160
166
  Fee actually paid: #{num(left, p)}
161
167
  Tx size: #{size} bytes
@@ -276,7 +282,7 @@ in block #{block} (by #{json[:provider]})")
276
282
  sat = fees[fee.to_sym]
277
283
  raise Error, "Can't understand the fee: #{fee.inspect}" if sat.nil?
278
284
  f = mul * sat * size
279
- @log.debug("Fee calculated as #{mul} * #{sat} * #{size} = #{f}")
285
+ @log.debug("Fee calculated as #{mul} * #{sat}s * #{size} = #{f}s")
280
286
  f
281
287
  end
282
288
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sibit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.30.4
4
+ version: 0.30.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko