sibit 0.32.7 → 0.32.8
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
- data/Gemfile.lock +2 -2
- data/features/cli.feature +1 -1
- data/features/dry.feature +0 -16
- data/features/fake.feature +25 -0
- data/lib/sibit/key.rb +27 -9
- data/lib/sibit/version.rb +1 -1
- data/lib/sibit.rb +23 -14
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8dbaecce413d6a977eee8d4d440a066a666f2054ad7d2b4cec0b21c6da4efe8e
|
|
4
|
+
data.tar.gz: 39431e80439522e9d000404ee29856f558ba3b4406976e9345e550f4efbf3974
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dc62197de1ada4a3e155148fa09926ffd02861178f1049203b1212a363b60d01d11fe3881f3e61d86a57b666464084d511aec4b4664e8fd038904468b9fb315f
|
|
7
|
+
data.tar.gz: f1ec0c729a1ccca0b2b9728ea23348db8cb5e5d80b22ec06dc33a682fb04a76c47cd0b487d578d8b19d2e62dfb7ac3c4f638aac03a9f8fa7a4c791f882e10259
|
data/Gemfile.lock
CHANGED
|
@@ -102,7 +102,7 @@ GEM
|
|
|
102
102
|
parser (3.3.10.0)
|
|
103
103
|
ast (~> 2.4.1)
|
|
104
104
|
racc
|
|
105
|
-
prism (1.
|
|
105
|
+
prism (1.8.0)
|
|
106
106
|
psych (5.3.1)
|
|
107
107
|
date
|
|
108
108
|
stringio
|
|
@@ -115,7 +115,7 @@ GEM
|
|
|
115
115
|
racc (1.8.1)
|
|
116
116
|
rainbow (3.1.1)
|
|
117
117
|
rake (13.3.1)
|
|
118
|
-
rdoc (7.0
|
|
118
|
+
rdoc (7.1.0)
|
|
119
119
|
erb
|
|
120
120
|
psych (>= 4.0.0)
|
|
121
121
|
tsort
|
data/features/cli.feature
CHANGED
|
@@ -33,7 +33,7 @@ Feature: Command Line Processing
|
|
|
33
33
|
Then Exit code is zero
|
|
34
34
|
|
|
35
35
|
Scenario: Bitcoin balance can be checked
|
|
36
|
-
When I run bin/sibit with "balance 1MZT1fa6y8H9UmbZV6HqKF4UY41o9MGT5f --verbose
|
|
36
|
+
When I run bin/sibit with "balance 1MZT1fa6y8H9UmbZV6HqKF4UY41o9MGT5f --verbose"
|
|
37
37
|
Then Exit code is zero
|
|
38
38
|
|
|
39
39
|
Scenario: Bitcoin fees can be printed
|
data/features/dry.feature
CHANGED
|
@@ -3,22 +3,6 @@
|
|
|
3
3
|
Feature: Command Line Processing
|
|
4
4
|
As a holder of BTC I want to use sibit in dry mode
|
|
5
5
|
|
|
6
|
-
Scenario: Bitcoin price can be retrieved
|
|
7
|
-
When I run bin/sibit with "price --dry --attempts=4"
|
|
8
|
-
Then Exit code is zero
|
|
9
|
-
|
|
10
|
-
Scenario: Bitcoin latest block hash can be retrieved
|
|
11
|
-
When I run bin/sibit with "latest --dry --api=blockchain"
|
|
12
|
-
Then Exit code is zero
|
|
13
|
-
|
|
14
|
-
Scenario: Bitcoin balance can be checked
|
|
15
|
-
When I run bin/sibit with "balance --dry 1MZT1fa6y8H9UmbZV6HqKF4UY41o9MGT5f --verbose --api=blockchain,btc"
|
|
16
|
-
Then Exit code is zero
|
|
17
|
-
|
|
18
|
-
Scenario: Bitcoin fees can be printed
|
|
19
|
-
When I run bin/sibit with "fees --dry --verbose --api=fake"
|
|
20
|
-
Then Exit code is zero
|
|
21
|
-
|
|
22
6
|
Scenario: Bitcoin payment can be sent
|
|
23
7
|
When I run bin/sibit with "pay --dry --verbose --api=fake --proxy=localhost:3128 999999 XL- 46feba063e9b59a8ae0dba68abd39a3cb8f52089e776576d6eb1bb5bfec123d1 1MZT1fa6y8H9UmbZV6HqKF4UY41o9MGT5f 1Fsyq5YGe8zbSjLS8YsDnZWM8U6AYMR6ZD"
|
|
24
8
|
Then Exit code is not zero
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
Feature: Command Line Processing
|
|
4
|
+
As a holder of BTC I want to use sibit with fake provider
|
|
5
|
+
|
|
6
|
+
Scenario: Bitcoin price can be retrieved
|
|
7
|
+
When I run bin/sibit with "price --attempts=4 --api=fake"
|
|
8
|
+
Then Exit code is zero
|
|
9
|
+
|
|
10
|
+
Scenario: Bitcoin latest block hash can be retrieved
|
|
11
|
+
When I run bin/sibit with "latest --api=fake"
|
|
12
|
+
Then Exit code is zero
|
|
13
|
+
|
|
14
|
+
Scenario: Bitcoin balance can be checked
|
|
15
|
+
When I run bin/sibit with "balance 1MZT1fa6y8H9UmbZV6HqKF4UY41o9MGT5f --verbose --api=fake"
|
|
16
|
+
Then Exit code is zero
|
|
17
|
+
|
|
18
|
+
Scenario: Bitcoin fees can be printed
|
|
19
|
+
When I run bin/sibit with "fees --verbose --api=fake"
|
|
20
|
+
Then Exit code is zero
|
|
21
|
+
|
|
22
|
+
Scenario: Bitcoin payment can be sent
|
|
23
|
+
When I run bin/sibit with "pay --verbose --api=fake --proxy=localhost:3128 999999 XL- 46feba063e9b59a8ae0dba68abd39a3cb8f52089e776576d6eb1bb5bfec123d1 1MZT1fa6y8H9UmbZV6HqKF4UY41o9MGT5f 1Fsyq5YGe8zbSjLS8YsDnZWM8U6AYMR6ZD"
|
|
24
|
+
Then Exit code is not zero
|
|
25
|
+
Then Stdout contains "UTXO arrived to 1JvCsJtLmCxEk7ddZFnVkGXpr9uhxZPmJi is incorrect"
|
data/lib/sibit/key.rb
CHANGED
|
@@ -7,6 +7,7 @@ require 'digest'
|
|
|
7
7
|
require 'openssl'
|
|
8
8
|
require_relative 'base58'
|
|
9
9
|
require_relative 'bech32'
|
|
10
|
+
require_relative 'error'
|
|
10
11
|
|
|
11
12
|
# Sibit main class.
|
|
12
13
|
class Sibit
|
|
@@ -61,24 +62,36 @@ class Sibit
|
|
|
61
62
|
def bech32
|
|
62
63
|
hrp = { mainnet: 'bc', testnet: 'tb', regtest: 'bcrt' }[@network]
|
|
63
64
|
hex = pub
|
|
64
|
-
raise 'Invalid public key: not on curve' unless @key.public_key.on_curve?
|
|
65
|
-
raise 'Invalid public key format' unless hex.match?(/\A0[23][0-9a-f]{64}\z/)
|
|
66
|
-
Bech32.encode(hrp, 0, hash160(hex))
|
|
65
|
+
raise Error, 'Invalid public key: not on curve' unless @key.public_key.on_curve?
|
|
66
|
+
raise Error, 'Invalid public key format' unless hex.match?(/\A0[23][0-9a-f]{64}\z/)
|
|
67
|
+
addr = Bech32.encode(hrp, 0, hash160(hex))
|
|
68
|
+
expected = /\A#{hrp}1q[a-z0-9]{38,58}\z/
|
|
69
|
+
raise Error, "Invalid bech32 address: #{addr}" unless addr.match?(expected)
|
|
70
|
+
addr
|
|
67
71
|
end
|
|
68
72
|
|
|
69
73
|
def base58
|
|
70
74
|
hex = pub
|
|
71
|
-
raise 'Invalid public key: not on curve' unless @key.public_key.on_curve?
|
|
72
|
-
raise 'Invalid public key format' unless hex.match?(/\A0[23][0-9a-f]{64}\z/)
|
|
75
|
+
raise Error, 'Invalid public key: not on curve' unless @key.public_key.on_curve?
|
|
76
|
+
raise Error, 'Invalid public key format' unless hex.match?(/\A0[23][0-9a-f]{64}\z/)
|
|
73
77
|
hash = hash160(hex)
|
|
74
78
|
prefix = @network == :mainnet ? '00' : '6f'
|
|
75
79
|
versioned = "#{prefix}#{hash}"
|
|
76
80
|
checksum = Base58.new(versioned).check
|
|
77
|
-
Base58.new(versioned + checksum).encode
|
|
81
|
+
addr = Base58.new(versioned + checksum).encode
|
|
82
|
+
mainnet = /\A1[1-9A-HJ-NP-Za-km-z]{25,34}\z/
|
|
83
|
+
testnet = /\A[mn][1-9A-HJ-NP-Za-km-z]{25,34}\z/
|
|
84
|
+
unless addr.match?(@network == :mainnet ? mainnet : testnet)
|
|
85
|
+
raise Error,
|
|
86
|
+
"Invalid base58 address: #{addr}"
|
|
87
|
+
end
|
|
88
|
+
addr
|
|
78
89
|
end
|
|
79
90
|
|
|
80
91
|
def sign(data)
|
|
81
|
-
@key.dsa_sign_asn1(data)
|
|
92
|
+
sig = @key.dsa_sign_asn1(data)
|
|
93
|
+
raise Error, 'Signature verification failed' unless verify(data, sig)
|
|
94
|
+
sig
|
|
82
95
|
end
|
|
83
96
|
|
|
84
97
|
def verify(data, sig)
|
|
@@ -91,7 +104,7 @@ class Sibit
|
|
|
91
104
|
|
|
92
105
|
def build(privkey)
|
|
93
106
|
value = privkey.to_i(16)
|
|
94
|
-
raise '
|
|
107
|
+
raise Error, 'Private key is not on curve' unless value.between?(MIN_PRIV, MAX_PRIV)
|
|
95
108
|
group = OpenSSL::PKey::EC::Group.new('secp256k1')
|
|
96
109
|
bn = OpenSSL::BN.new(privkey, 16)
|
|
97
110
|
pubkey = group.generator.mul(bn)
|
|
@@ -114,10 +127,15 @@ class Sibit
|
|
|
114
127
|
def decode(key)
|
|
115
128
|
if key.length == 64 && key.match?(/\A[0-9a-f]+\z/i)
|
|
116
129
|
@network = @override || :mainnet
|
|
117
|
-
return key
|
|
130
|
+
return key.downcase
|
|
118
131
|
end
|
|
119
132
|
raw = Base58.new(key).decode
|
|
133
|
+
payload = raw[0..-9]
|
|
134
|
+
checksum = raw[-8..]
|
|
135
|
+
expected = Base58.new(payload).check
|
|
136
|
+
raise Error, 'Invalid WIF checksum' unless checksum == expected
|
|
120
137
|
version = raw[0, 2]
|
|
138
|
+
raise Error, "Invalid WIF version: #{version}" unless %w[80 ef].include?(version)
|
|
121
139
|
detected = version == '80' ? :mainnet : :testnet
|
|
122
140
|
@network = @override || detected
|
|
123
141
|
body = raw[2..-9]
|
data/lib/sibit/version.rb
CHANGED
data/lib/sibit.rb
CHANGED
|
@@ -53,7 +53,7 @@ class Sibit
|
|
|
53
53
|
# Generates new Bitcoin private key and returns in Hash160 format.
|
|
54
54
|
def generate
|
|
55
55
|
key = Key.generate.priv
|
|
56
|
-
@log.debug("Bitcoin private key generated: #{key
|
|
56
|
+
@log.debug("Bitcoin private key generated: #{key.ellipsized(8)}...")
|
|
57
57
|
key
|
|
58
58
|
end
|
|
59
59
|
|
|
@@ -181,19 +181,28 @@ class Sibit
|
|
|
181
181
|
change_address: change
|
|
182
182
|
)
|
|
183
183
|
left = unspent - tx.outputs.sum(&:value)
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
184
|
+
has_change = tx.out.count > 1
|
|
185
|
+
@log.debug(
|
|
186
|
+
[
|
|
187
|
+
"A new Bitcoin transaction #{tx.hash} prepared:",
|
|
188
|
+
"#{tx.in.count} input#{'s' if tx.in.count > 1}:",
|
|
189
|
+
tx.inputs.map do |i|
|
|
190
|
+
" in: #{i.prev_out.unpack1('H*')}:#{i.prev_out_index}"
|
|
191
|
+
end,
|
|
192
|
+
"#{tx.out.count} output#{'s' if tx.out.count > 1}:",
|
|
193
|
+
tx.outputs.map do |o|
|
|
194
|
+
" out: #{o.script_hex} / #{num(o.value, p)}"
|
|
195
|
+
end,
|
|
196
|
+
"Min fee: #{num(MIN_SATOSHI_PER_BYTE, p)} /byte",
|
|
197
|
+
"Fee requested: #{num(f, p)} as \"#{fee}\"",
|
|
198
|
+
"Fee actually paid: #{num(left, p)}",
|
|
199
|
+
"Tx size: #{size} bytes",
|
|
200
|
+
"Unspent: #{num(unspent, p)}",
|
|
201
|
+
"Amount: #{num(satoshi, p)}",
|
|
202
|
+
"Target address: #{target}",
|
|
203
|
+
("Change address: #{change}" if has_change)
|
|
204
|
+
].flatten.compact.join("\n")
|
|
205
|
+
)
|
|
197
206
|
@api.push(tx.to_payload.bth)
|
|
198
207
|
tx.hash
|
|
199
208
|
end
|
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.32.
|
|
4
|
+
version: 0.32.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yegor Bugayenko
|
|
@@ -171,6 +171,7 @@ files:
|
|
|
171
171
|
- cucumber.yml
|
|
172
172
|
- features/cli.feature
|
|
173
173
|
- features/dry.feature
|
|
174
|
+
- features/fake.feature
|
|
174
175
|
- features/gem_package.feature
|
|
175
176
|
- features/step_definitions/steps.rb
|
|
176
177
|
- features/support/env.rb
|