sibit 0.33.0 → 0.34.1

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: 7fc905f4a84df3f625583d1d3b628d1639e830daec2fb9f729a2361bdbc79443
4
- data.tar.gz: 95957394b7411ce0140b765f3806d9869854666d5a882a00aa7b2a5f70b9fc4d
3
+ metadata.gz: 469905d53f542975d0fe59c8b429289423762f4b36aca8b703928d54f5ba394f
4
+ data.tar.gz: c68a4237d70f25a11ea2e98c36d76c7b0917a6355353e6d23c22336eedd94f31
5
5
  SHA512:
6
- metadata.gz: 68030b89ec041f142967f24f3d84ce481330ccb5828da88902aed944be0b26452f45fa361fb503b83feac2242ff4a284d2fa530cb6381da634258927a9ce06b4
7
- data.tar.gz: 2d206f21e0129d28ef450c63afbf18b6d9c7a70a45a583d4b9554ead31fc598dab9af208bdced8744e3e92b9f56035451c6760f58df6d6152e935e18f491c93f
6
+ metadata.gz: f5aa717192c0417c572226c3a0f79924f61e5d70b0bc84efe53d0cc760c16515f3cd6ef63b00de57e4228dbcd82fdb60a269f35df858b0c1ff8bec81006db6bc
7
+ data.tar.gz: fe9f402e207051f02e31b54d0a4e41cca76efd2a0260fbc6dfb3fb69f1aa543af2a9af6045590bd653c6c26472c97fdb6d5ba3a8b5a98f4ca282e351d88f53ee
data/Gemfile CHANGED
@@ -6,10 +6,8 @@
6
6
  source 'https://rubygems.org'
7
7
  gemspec
8
8
 
9
- # gem 'debase', '0.2.4.1', require: false
10
-
11
9
  gem 'aruba', '~>2.2', require: false
12
- gem 'cucumber', '~>10.0', require: false
10
+ gem 'cucumber', '~>11.0', require: false
13
11
  gem 'donce', '~>0.2', require: false
14
12
  gem 'logger', '~>1.7', require: false
15
13
  gem 'minitest', '~>6.0', require: false
@@ -18,8 +16,9 @@ gem 'nokogiri', '~>1.18', require: false
18
16
  gem 'os', '~>1.1', require: false
19
17
  gem 'qbash', '~>0.0', require: false
20
18
  gem 'rake', '~>13.2', require: false
21
- gem 'rdoc', '~>7.0', require: false
22
- gem 'rubocop', '~>1.62', require: false
19
+ gem 'rdoc', '~>8.0', require: false
20
+ gem 'rubocop', '~>1.72', require: false
21
+ gem 'rubocop-elegant', '~>0.5', require: false
23
22
  gem 'rubocop-minitest', '~>0.38', require: false
24
23
  gem 'rubocop-performance', '~>1.25', require: false
25
24
  gem 'rubocop-rake', '~>0.7', require: false
data/Gemfile.lock CHANGED
@@ -16,133 +16,152 @@ PATH
16
16
  GEM
17
17
  remote: https://rubygems.org/
18
18
  specs:
19
- addressable (2.8.8)
19
+ addressable (2.9.0)
20
20
  public_suffix (>= 2.0.2, < 8.0)
21
- ansi (1.5.0)
22
- aruba (2.3.3)
21
+ ansi (1.6.0)
22
+ aruba (2.4.1)
23
23
  bundler (>= 1.17)
24
24
  contracts (>= 0.16.0, < 0.18.0)
25
- cucumber (>= 8.0, < 11.0)
25
+ cucumber (>= 8.0, < 12.0)
26
+ irb (~> 1.16)
26
27
  rspec-expectations (>= 3.4, < 5.0)
27
28
  thor (~> 1.0)
28
29
  ast (2.4.3)
29
30
  backtrace (0.4.1)
30
31
  base64 (0.3.0)
31
- bigdecimal (4.0.1)
32
+ bigdecimal (4.1.2)
32
33
  builder (3.3.0)
33
34
  contracts (0.17.3)
34
35
  crack (1.0.1)
35
36
  bigdecimal
36
37
  rexml
37
- cucumber (10.2.0)
38
+ cucumber (11.1.1)
38
39
  base64 (~> 0.2)
39
40
  builder (~> 3.2)
40
41
  cucumber-ci-environment (> 9, < 12)
41
- cucumber-core (> 15, < 17)
42
+ cucumber-core (>= 16.2.0, < 17)
42
43
  cucumber-cucumber-expressions (> 17, < 20)
43
- cucumber-html-formatter (> 21, < 23)
44
+ cucumber-html-formatter (> 21, < 24)
44
45
  diff-lcs (~> 1.5)
45
46
  logger (~> 1.6)
46
47
  mini_mime (~> 1.1)
47
48
  multi_test (~> 1.1)
48
- sys-uname (~> 1.3)
49
+ sys-uname (~> 1.5)
49
50
  cucumber-ci-environment (11.0.0)
50
- cucumber-core (16.1.1)
51
+ cucumber-core (16.2.0)
51
52
  cucumber-gherkin (> 36, < 40)
52
53
  cucumber-messages (> 31, < 33)
53
54
  cucumber-tag-expressions (> 6, < 9)
54
- cucumber-cucumber-expressions (18.0.1)
55
+ cucumber-cucumber-expressions (19.0.1)
55
56
  bigdecimal
56
- cucumber-gherkin (37.0.1)
57
- cucumber-messages (>= 31, < 32)
58
- cucumber-html-formatter (22.3.0)
57
+ cucumber-gherkin (39.1.0)
58
+ cucumber-messages (>= 31, < 33)
59
+ cucumber-html-formatter (23.1.0)
59
60
  cucumber-messages (> 23, < 33)
60
- cucumber-messages (31.2.0)
61
+ cucumber-messages (32.3.1)
61
62
  cucumber-tag-expressions (8.1.0)
62
- date (3.5.1)
63
63
  decoor (0.1.0)
64
64
  diff-lcs (1.6.2)
65
65
  docile (1.4.1)
66
- donce (0.4.0)
66
+ donce (0.7.0)
67
67
  backtrace (~> 0.3)
68
68
  os (~> 1.1)
69
69
  qbash (~> 0.3)
70
- elapsed (0.2.2)
70
+ drb (2.2.3)
71
+ elapsed (0.3.1)
71
72
  loog (~> 0.6)
72
73
  tago (~> 0.1)
73
74
  ellipsized (0.3.0)
74
- erb (6.0.1)
75
- ffi (1.17.3-arm64-darwin)
76
- ffi (1.17.3-x86_64-linux-gnu)
75
+ erb (6.0.6)
76
+ ffi (1.17.4-arm64-darwin)
77
+ ffi (1.17.4-x86_64-linux-gnu)
77
78
  hashdiff (1.2.1)
78
- iri (0.11.6)
79
- json (2.18.0)
80
- language_server-protocol (3.17.0.5)
79
+ io-console (0.8.2)
80
+ irb (1.18.0)
81
+ pp (>= 0.6.0)
82
+ prism (>= 1.3.0)
83
+ rdoc (>= 4.0.0)
84
+ reline (>= 0.4.2)
85
+ iri (0.11.8)
86
+ json (2.21.1)
87
+ language_server-protocol (3.17.0.6)
81
88
  lint_roller (1.1.0)
82
89
  logger (1.7.0)
83
- loog (0.6.1)
90
+ loog (0.8.0)
91
+ ellipsized
84
92
  logger (~> 1.0)
85
93
  memoist3 (1.0.0)
86
94
  mini_mime (1.1.5)
87
- minitest (6.0.1)
95
+ minitest (6.0.6)
96
+ drb (~> 2.0)
88
97
  prism (~> 1.5)
89
- minitest-reporters (1.7.1)
98
+ minitest-reporters (1.8.0)
90
99
  ansi
91
100
  builder
92
- minitest (>= 5.0)
101
+ minitest (>= 5.0, < 7)
93
102
  ruby-progressbar
94
103
  multi_test (1.1.0)
95
- nokogiri (1.19.0-arm64-darwin)
104
+ nokogiri (1.19.4-arm64-darwin)
96
105
  racc (~> 1.4)
97
- nokogiri (1.19.0-x86_64-linux-gnu)
106
+ nokogiri (1.19.4-x86_64-linux-gnu)
98
107
  racc (~> 1.4)
99
- openssl (3.3.2)
108
+ openssl (3.3.3)
100
109
  os (1.1.4)
101
- parallel (1.27.0)
102
- parser (3.3.10.0)
110
+ parallel (2.1.0)
111
+ parser (3.3.12.0)
103
112
  ast (~> 2.4.1)
104
113
  racc
105
- prism (1.8.0)
106
- psych (5.3.1)
107
- date
108
- stringio
109
- public_suffix (7.0.2)
110
- qbash (0.5.0)
114
+ pp (0.6.4)
115
+ prettyprint
116
+ prettyprint (0.2.0)
117
+ prism (1.9.0)
118
+ public_suffix (7.0.5)
119
+ qbash (0.8.4)
111
120
  backtrace (> 0)
112
121
  elapsed (> 0)
113
122
  loog (> 0)
114
123
  tago (> 0)
115
124
  racc (1.8.1)
116
125
  rainbow (3.1.1)
117
- rake (13.3.1)
118
- rdoc (7.1.0)
126
+ rake (13.4.2)
127
+ rbs (4.0.3)
128
+ logger
129
+ prism (>= 1.6.0)
130
+ tsort
131
+ rdoc (8.0.0)
119
132
  erb
120
- psych (>= 4.0.0)
133
+ prism (>= 1.6.0)
134
+ rbs (>= 4.0.0)
121
135
  tsort
122
- regexp_parser (2.11.3)
123
- retriable (3.1.2)
136
+ regexp_parser (2.12.0)
137
+ reline (0.6.3)
138
+ io-console (~> 0.5)
139
+ retriable (3.8.0)
124
140
  retriable_proxy (1.0.2)
125
141
  retriable (>= 2.0, < 4.0)
126
142
  rexml (3.4.4)
127
143
  rspec-expectations (3.13.5)
128
144
  diff-lcs (>= 1.2.0, < 2.0)
129
145
  rspec-support (~> 3.13.0)
130
- rspec-support (3.13.6)
131
- rubocop (1.82.1)
146
+ rspec-support (3.13.7)
147
+ rubocop (1.88.2)
132
148
  json (~> 2.3)
133
149
  language_server-protocol (~> 3.17.0.2)
134
150
  lint_roller (~> 1.1.0)
135
- parallel (~> 1.10)
151
+ parallel (>= 1.10)
136
152
  parser (>= 3.3.0.2)
137
153
  rainbow (>= 2.2.2, < 4.0)
138
154
  regexp_parser (>= 2.9.3, < 3.0)
139
- rubocop-ast (>= 1.48.0, < 2.0)
155
+ rubocop-ast (>= 1.49.0, < 2.0)
140
156
  ruby-progressbar (~> 1.7)
141
157
  unicode-display_width (>= 2.4.0, < 4.0)
142
- rubocop-ast (1.49.0)
158
+ rubocop-ast (1.50.0)
143
159
  parser (>= 3.3.7.2)
144
160
  prism (~> 1.7)
145
- rubocop-minitest (0.38.2)
161
+ rubocop-elegant (0.7.1)
162
+ lint_roller (~> 1.1)
163
+ rubocop (~> 1.75)
164
+ rubocop-minitest (0.40.0)
146
165
  lint_roller (~> 1.1)
147
166
  rubocop (>= 1.75.0, < 2.0)
148
167
  rubocop-ast (>= 1.38.0, < 2.0)
@@ -158,22 +177,21 @@ GEM
158
177
  docile (~> 1.1)
159
178
  simplecov-html (~> 0.11)
160
179
  simplecov_json_formatter (~> 0.1)
161
- simplecov-cobertura (3.1.0)
180
+ simplecov-cobertura (3.2.0)
162
181
  rexml
163
182
  simplecov (~> 0.19)
164
183
  simplecov-html (0.13.2)
165
184
  simplecov_json_formatter (0.1.4)
166
- stringio (3.2.0)
167
- sys-uname (1.4.1)
185
+ sys-uname (1.5.1)
168
186
  ffi (~> 1.1)
169
187
  memoist3 (~> 1.0.0)
170
- tago (0.6.0)
188
+ tago (0.7.0)
171
189
  thor (1.5.0)
172
190
  tsort (0.2.0)
173
191
  unicode-display_width (3.2.0)
174
192
  unicode-emoji (~> 4.1)
175
193
  unicode-emoji (4.2.0)
176
- webmock (3.26.1)
194
+ webmock (3.26.2)
177
195
  addressable (>= 2.8.0)
178
196
  crack (>= 0.3.2)
179
197
  hashdiff (>= 0.4.0, < 2.0.0)
@@ -182,11 +200,12 @@ PLATFORMS
182
200
  arm64-darwin-22
183
201
  arm64-darwin-23
184
202
  arm64-darwin-24
203
+ arm64-darwin-25
185
204
  x86_64-linux
186
205
 
187
206
  DEPENDENCIES
188
207
  aruba (~> 2.2)
189
- cucumber (~> 10.0)
208
+ cucumber (~> 11.0)
190
209
  donce (~> 0.2)
191
210
  logger (~> 1.7)
192
211
  minitest (~> 6.0)
@@ -195,8 +214,9 @@ DEPENDENCIES
195
214
  os (~> 1.1)
196
215
  qbash (~> 0.0)
197
216
  rake (~> 13.2)
198
- rdoc (~> 7.0)
199
- rubocop (~> 1.62)
217
+ rdoc (~> 8.0)
218
+ rubocop (~> 1.72)
219
+ rubocop-elegant (~> 0.5)
200
220
  rubocop-minitest (~> 0.38)
201
221
  rubocop-performance (~> 1.25)
202
222
  rubocop-rake (~> 0.7)
data/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![rake](https://github.com/yegor256/sibit/actions/workflows/rake.yml/badge.svg)](https://github.com/yegor256/sibit/actions/workflows/rake.yml)
8
8
  [![PDD status](https://www.0pdd.com/svg?name=yegor256/sibit)](https://www.0pdd.com/p?name=yegor256/sibit)
9
9
  [![Gem Version](https://badge.fury.io/rb/sibit.svg)](https://badge.fury.io/rb/sibit)
10
- [![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/yegor256/takes/sibit/master/LICENSE.txt)
10
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/yegor256/sibit/blob/master/LICENSE.txt)
11
11
  [![Test Coverage](https://img.shields.io/codecov/c/github/yegor256/sibit.svg)](https://codecov.io/github/yegor256/sibit?branch=master)
12
12
  [![Hits-of-Code](https://hitsofcode.com/github/yegor256/sibit)](https://hitsofcode.com/view/github/yegor256/sibit)
13
13
 
@@ -80,7 +80,7 @@ Not all [UTXOs] may be used, but only the necessary amount of them.
80
80
 
81
81
  By default, the fee is paid on top of the payment amount you are sending.
82
82
  Say, you are sending 0.5 BTC and the fee is 0.0001 BTC.
83
- Totally, you spend 0.5001.
83
+ In total, you spend 0.5001 BTC.
84
84
  However, you can make Sibit deduct the fee from the payment amount.
85
85
  In this case you should provide a negative amount
86
86
  of the fee or one of `S-`, `M-`, `L-`, `XL-`.
@@ -91,6 +91,18 @@ It is recommended to run it with `--dry --verbose` options first,
91
91
  If everything looks correct, remove the `--dry` and run again,
92
92
  the transaction is pushed to the network.
93
93
 
94
+ To require a minimum number of confirmations on every UTXO before it is
95
+ spent, or before it counts toward the reported balance, pass `--trust`:
96
+
97
+ ```bash
98
+ sibit --trust=6 balance 1PfsYNygsuVL8fvBarJNQnHytkg4rGih1U
99
+ sibit --trust=6 pay 10000 S P1,P2 TARGET CHANGE
100
+ ```
101
+
102
+ The default is `0`, which preserves the existing behavior.
103
+ The same option is available from the Ruby SDK via the `trust:` keyword
104
+ argument on `Sibit#balance` and `Sibit#pay`.
105
+
94
106
  To use an HTTPS proxy for all requests:
95
107
 
96
108
  ```bash
@@ -103,6 +115,11 @@ The proxy address may include authentication credentials:
103
115
  sibit --proxy=user:password@host:port balance 1PfsYNygsuVL8fvBarJNQnHytkg4rGih1U
104
116
  ```
105
117
 
118
+ Some providers accept an API key, read from an environment variable:
119
+ `SIBIT_BLOCKCHAIR_KEY` for [Blockchair.com] and
120
+ `SIBIT_CRYPTOAPIS_KEY` for [Cryptoapis.io].
121
+ When the variable is set, requests to that provider use the authenticated tier.
122
+
106
123
  All operations are performed through the [Blockchain API].
107
124
  Transactions are pushed to the Bitcoin network via [this relay].
108
125
 
@@ -135,6 +152,7 @@ At the moment we work with the following APIs:
135
152
  * [Bitcoinchain.com] - `Sibit::Bitcoinchain`
136
153
  * [Blockchair.com] - `Sibit::Blockchair`
137
154
  * [Cex.io] - `Sibit::Cex`
155
+ * [SoChain] - `Sibit::Sochain`
138
156
 
139
157
  The first one in this list is used by default.
140
158
  If you want to use a different one,
@@ -211,6 +229,7 @@ If it's clean and you don't see any error messages, submit your pull request.
211
229
  [Cex.io]: https://cex.io/rest-api
212
230
  [Cryptoapis.io]: https://docs.cryptoapis.io/rest-apis/blockchain-as-a-service-apis/btc/index
213
231
  [Electrum]: https://electrum.org/
232
+ [SoChain]: https://sochain.com/api
214
233
  [miner fee]: https://en.bitcoin.it/wiki/Miner_fees
215
234
  [private key]: https://en.bitcoin.it/wiki/Private_key
216
235
  [Ruby]: https://www.ruby-lang.org/en/
data/Rakefile CHANGED
@@ -35,7 +35,7 @@ task :picks do
35
35
  next if OS.windows?
36
36
  %w[lib].each do |d|
37
37
  Dir["#{d}/**/*.rb"].each do |f|
38
- qbash("bundle exec ruby #{Shellwords.escape(f)}", log: $stdout, env: { 'PICKS' => 'yes' })
38
+ qbash("bundle exec ruby #{Shellwords.escape(f)}", stdout: $stdout, env: { 'PICKS' => 'yes' })
39
39
  end
40
40
  end
41
41
  end
data/bin/sibit CHANGED
@@ -10,23 +10,25 @@ require 'backtrace'
10
10
  require 'loog'
11
11
  require_relative '../lib/sibit'
12
12
  require_relative '../lib/sibit/bin'
13
- require_relative '../lib/sibit/http'
14
- require_relative '../lib/sibit/httpproxy'
15
13
  require_relative '../lib/sibit/bitcoinchain'
16
14
  require_relative '../lib/sibit/blockchain'
17
15
  require_relative '../lib/sibit/blockchair'
18
16
  require_relative '../lib/sibit/btc'
19
17
  require_relative '../lib/sibit/cex'
18
+ require_relative '../lib/sibit/cryptoapis'
20
19
  require_relative '../lib/sibit/dry'
21
20
  require_relative '../lib/sibit/fake'
22
21
  require_relative '../lib/sibit/firstof'
22
+ require_relative '../lib/sibit/http'
23
+ require_relative '../lib/sibit/httpproxy'
24
+ require_relative '../lib/sibit/sochain'
23
25
  require_relative '../lib/sibit/version'
24
26
 
25
27
  begin
26
28
  Sibit::Bin.start(ARGV)
27
29
  rescue StandardError => e
28
- verbose = !ARGV.include?('--quiet') &&
29
- (ARGV.include?('--verbose') || ENV.fetch('SIBIT_VERBOSE', nil))
30
+ wants = ARGV.include?('--verbose') || ENV.fetch('SIBIT_VERBOSE', nil)
31
+ verbose = !ARGV.include?('--quiet') && wants
30
32
  log = verbose ? Loog::VERBOSE : Loog::REGULAR
31
33
  if verbose
32
34
  log.error(Backtrace.new(e))
data/cross/alpine.df ADDED
@@ -0,0 +1,6 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ FROM alpine:3.21
5
+
6
+ RUN apk add --no-cache ruby ruby-dev gcc make musl-dev openssl-dev bash
data/cross/centos.df ADDED
@@ -0,0 +1,8 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ FROM quay.io/centos/centos:stream9
5
+
6
+ RUN dnf module enable -y ruby:3.3 && \
7
+ dnf install -y ruby ruby-devel gcc make openssl-devel redhat-rpm-config && \
8
+ dnf clean all
data/cross/debian.df ADDED
@@ -0,0 +1,9 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ FROM debian:trixie
5
+
6
+ RUN apt-get update && \
7
+ apt-get install -y ruby ruby-dev gcc make libssl-dev && \
8
+ apt-get clean && \
9
+ rm -rf /var/lib/apt/lists/*
data/cross/fedora.df ADDED
@@ -0,0 +1,7 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ FROM fedora:41
5
+
6
+ RUN dnf install -y ruby ruby-devel gcc make openssl-devel && \
7
+ dnf clean all
data/cross/opensuse.df ADDED
@@ -0,0 +1,17 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ FROM opensuse/tumbleweed
5
+
6
+ RUN ok=; \
7
+ for i in 1 2 3 4 5; do \
8
+ if zypper --non-interactive --gpg-auto-import-keys refresh && \
9
+ zypper --non-interactive install ruby ruby-devel gcc make libopenssl-devel bash; then \
10
+ ok=1; break; \
11
+ fi; \
12
+ echo "zypper attempt $i failed, retrying in 15s"; sleep 15; \
13
+ done; \
14
+ test -n "$ok" && \
15
+ zypper clean --all && \
16
+ gem update --system --no-document && \
17
+ sed -i '/format.executable/d' /etc/gemrc
data/cross/rocky.df ADDED
@@ -0,0 +1,8 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ FROM rockylinux:9
5
+
6
+ RUN dnf module enable -y ruby:3.3 && \
7
+ dnf install -y ruby ruby-devel gcc make openssl-devel redhat-rpm-config && \
8
+ dnf clean all
data/cross/ubuntu.df ADDED
@@ -0,0 +1,9 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ FROM ubuntu:24.04
5
+
6
+ RUN apt-get update && \
7
+ apt-get install -y ruby ruby-dev gcc make libssl-dev && \
8
+ apt-get clean && \
9
+ rm -rf /var/lib/apt/lists/*
@@ -3,9 +3,9 @@
3
3
  # SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
+ require 'English'
6
7
  require 'nokogiri'
7
8
  require 'tmpdir'
8
- require 'English'
9
9
  require_relative '../../lib/sibit'
10
10
 
11
11
  Before do
@@ -32,19 +32,19 @@ When(%r{^I run bin/sibit with "([^"]*)"$}) do |arg|
32
32
  end
33
33
 
34
34
  Then(/^Stdout contains "([^"]*)"$/) do |txt|
35
- raise "STDOUT doesn't contain '#{txt}':\n#{@stdout}" unless @stdout.include?(txt)
35
+ raise(StandardError, "STDOUT doesn't contain '#{txt}':\n#{@stdout}") unless @stdout.include?(txt)
36
36
  end
37
37
 
38
38
  Then(/^Stdout is empty$/) do
39
- raise "STDOUT is not empty:\n#{@stdout}" unless @stdout == ''
39
+ raise(StandardError, "STDOUT is not empty:\n#{@stdout}") unless @stdout == ''
40
40
  end
41
41
 
42
42
  Then(/^Exit code is zero$/) do
43
- raise "Non-zero exit #{@exitstatus}:\n#{@stdout}" unless @exitstatus.zero?
43
+ raise(StandardError, "Non-zero exit #{@exitstatus}:\n#{@stdout}") unless @exitstatus.zero?
44
44
  end
45
45
 
46
46
  Then(/^Exit code is not zero$/) do
47
- raise 'Zero exit code' if @exitstatus.zero?
47
+ raise(StandardError, 'Zero exit code') if @exitstatus.zero?
48
48
  end
49
49
 
50
50
  When(/^I run bash with "([^"]*)"$/) do |text|
@@ -3,6 +3,6 @@
3
3
  # SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
- require 'simplecov'
7
6
  require 'aruba/cucumber'
7
+ require 'simplecov'
8
8
  require_relative '../../lib/sibit'
data/lib/sibit/base58.rb CHANGED
@@ -23,28 +23,25 @@ class Sibit
23
23
  end
24
24
 
25
25
  def encode
26
- bytes = [@data].pack('H*')
27
- leading = bytes.match(/^\x00*/)[0].length
28
26
  num = @data.to_i(16)
29
27
  result = ''
30
28
  while num.positive?
31
29
  num, remainder = num.divmod(58)
32
30
  result = ALPHABET[remainder] + result
33
31
  end
34
- ('1' * leading) + result
32
+ ('1' * [@data].pack('H*').match(/^\x00*/)[0].length) + result
35
33
  end
36
34
 
37
35
  def decode
38
- leading = @data.match(/^1*/)[0].length
39
36
  num = 0
40
37
  @data.each_char do |c|
41
38
  idx = ALPHABET.index(c)
42
- raise Sibit::Error, "Invalid Base58 character '#{c}' in address '#{@data}'" if idx.nil?
39
+ raise(Sibit::Error, "Invalid Base58 character '#{c}' in address '#{@data}'") if idx.nil?
43
40
  num = (num * 58) + idx
44
41
  end
45
42
  hex = num.zero? ? '' : num.to_s(16)
46
43
  hex = "0#{hex}" if hex.length.odd?
47
- ('00' * leading) + hex
44
+ ('00' * @data.match(/^1*/)[0].length) + hex
48
45
  end
49
46
 
50
47
  def check
data/lib/sibit/bech32.rb CHANGED
@@ -19,15 +19,13 @@ class Sibit
19
19
  GENERATOR = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3].freeze
20
20
 
21
21
  def self.encode(hrp, ver, prog)
22
- bytes = [prog].pack('H*').bytes
23
- data = [ver] + bits(bytes, 8, 5, true)
22
+ data = [ver] + bits([prog].pack('H*').bytes, 8, 5, true)
24
23
  chk = checksum(hrp, data)
25
24
  "#{hrp}1#{(data + chk).map { |d| CHARSET[d] }.join}"
26
25
  end
27
26
 
28
27
  def self.checksum(hrp, data)
29
- values = expanded(hrp) + data + [0, 0, 0, 0, 0, 0]
30
- poly = pm(values) ^ 1
28
+ poly = pm(expanded(hrp) + data + [0, 0, 0, 0, 0, 0]) ^ 1
31
29
  (0..5).map { |i| (poly >> (5 * (5 - i))) & 31 }
32
30
  end
33
31
 
@@ -68,8 +66,18 @@ class Sibit
68
66
 
69
67
  def witness
70
68
  hrp, data = parse
71
- raise Sibit::Error, "Invalid Bech32 checksum in '#{@addr}'" unless verified?(hrp, data)
72
- prog = convert(data[1..-7], 5, 8, false)
69
+ ver = data[0]
70
+ unless ver.between?(0, 16)
71
+ raise(Sibit::Error, "Unsupported witness version #{ver} in '#{@addr}'")
72
+ end
73
+ raise(Sibit::Error, "Invalid Bech32 checksum in '#{@addr}'") unless verified?(hrp, data)
74
+ prog = convert(data[1..-7], 5, 8)
75
+ if ver.zero? && [20, 32].none?(prog.length)
76
+ raise(Sibit::Error, "Witness v0 program in '#{@addr}' must be 20 or 32 bytes")
77
+ end
78
+ unless prog.length.between?(2, 40)
79
+ raise(Sibit::Error, "Witness program in '#{@addr}' must be 2 to 40 bytes")
80
+ end
73
81
  prog.pack('C*').unpack1('H*')
74
82
  end
75
83
 
@@ -82,18 +90,16 @@ class Sibit
82
90
 
83
91
  def parse
84
92
  pos = @addr.rindex('1')
85
- raise Sibit::Error, "Invalid Bech32 address '#{@addr}': no separator" if pos.nil? || pos < 1
86
- hrp = @addr[0...pos]
93
+ raise(Sibit::Error, "Invalid Bech32 address '#{@addr}': no separator") if pos.nil? || pos < 1
87
94
  rest = @addr[(pos + 1)..]
88
- raise Sibit::Error, "Invalid Bech32 address '#{@addr}': data too short" if rest.length < 6
95
+ raise(Sibit::Error, "Invalid Bech32 address '#{@addr}': data too short") if rest.length < 6
89
96
  data = rest.chars.map { |c| CHARSET.index(c) }
90
- raise Sibit::Error, "Invalid Bech32 character in '#{@addr}'" if data.include?(nil)
91
- [hrp, data]
97
+ raise(Sibit::Error, "Invalid Bech32 character in '#{@addr}'") if data.include?(nil)
98
+ [@addr[0...pos], data]
92
99
  end
93
100
 
94
101
  def verified?(hrp, data)
95
- chk = polymod(expand(hrp) + data)
96
- [1, 0x2bc830a3].include?(chk)
102
+ polymod(expand(hrp) + data) == (data[0].zero? ? 1 : 0x2bc830a3)
97
103
  end
98
104
 
99
105
  def expand(hrp)
@@ -110,7 +116,7 @@ class Sibit
110
116
  chk
111
117
  end
112
118
 
113
- def convert(data, frombits, tobits, pad)
119
+ def convert(data, frombits, tobits)
114
120
  acc = 0
115
121
  bits = 0
116
122
  result = []
@@ -123,7 +129,9 @@ class Sibit
123
129
  result << ((acc >> bits) & maxv)
124
130
  end
125
131
  end
126
- result << ((acc << (tobits - bits)) & maxv) if pad && bits.positive?
132
+ if bits >= frombits || (acc << (tobits - bits)).anybits?(maxv)
133
+ raise(Sibit::Error, "Non-zero padding in Bech32 address '#{@addr}'")
134
+ end
127
135
  result
128
136
  end
129
137
  end