sibit 0.30.2 → 0.30.3

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: 7463ec26890a5bd8515ce96c92190a50edaf46f5b94aed0a1b54261f0d63ca65
4
- data.tar.gz: 71be0a78c7bfcfffdebc6daa2c63a570d561b5e6e923f0d600e2791c2856cac5
3
+ metadata.gz: 668856721cd11cf3b3dac9c5c45f875f7d85792bc4599730a0ce29e04446ec08
4
+ data.tar.gz: f740776c9a3008aca1b8dea3a55be5220dea2eb6a198561ca7c7cc0d43d54d27
5
5
  SHA512:
6
- metadata.gz: ae0606a033a0506be0d3f397a0ac81bf51db53e7c35671256642764e2dcca358d95cbb9517c67c0a49f0621110926760154ea1c1c885d4aa5b6a2a32792078ff
7
- data.tar.gz: 21a0bf5f5e27f3c22ceb82f2432d3b3fdd8a4ae1181cbdad383d34f081024c4802b6c83c2a7f51c1205728ccede22c8e45c8498f2d74ffd04282f828b29b4c54
6
+ metadata.gz: 9fd451884b64a7cc40478b4652e0d7466f718ae7263ec7a08a4023ad3c6e1b2cfb7d0c73e3b46bfd3be6612696bb2955f4e9fded0beb7e96996ff8ef1d005d60
7
+ data.tar.gz: bf52a162a4458d4131695c7acbf0e047255f826e1d37a6235471144377ca0407679468c88647eb8454262907271dd429c8adfded3bf58b379b65f7933862dcbc
data/lib/sibit/base58.rb CHANGED
@@ -4,6 +4,7 @@
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
6
  require 'digest'
7
+ require_relative 'error'
7
8
 
8
9
  # Sibit main class.
9
10
  class Sibit
@@ -36,7 +37,11 @@ class Sibit
36
37
  def decode
37
38
  leading = @data.match(/^1*/)[0].length
38
39
  num = 0
39
- @data.each_char { |c| num = (num * 58) + ALPHABET.index(c) }
40
+ @data.each_char do |c|
41
+ idx = ALPHABET.index(c)
42
+ raise Sibit::Error, "Invalid Base58 character '#{c}' in address '#{@data}'" if idx.nil?
43
+ num = (num * 58) + idx
44
+ end
40
45
  hex = num.zero? ? '' : num.to_s(16)
41
46
  hex = "0#{hex}" if hex.length.odd?
42
47
  ('00' * leading) + hex
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ # SPDX-FileCopyrightText: Copyright (c) 2019-2025 Yegor Bugayenko
4
+ # SPDX-License-Identifier: MIT
5
+
6
+ require_relative 'error'
7
+
8
+ # Sibit main class.
9
+ class Sibit
10
+ # Bech32 decoding for SegWit addresses.
11
+ #
12
+ # Decodes Bech32/Bech32m addresses (bc1...) to witness programs.
13
+ #
14
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
15
+ # Copyright:: Copyright (c) 2019-2025 Yegor Bugayenko
16
+ # License:: MIT
17
+ class Bech32
18
+ CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l'
19
+ GENERATOR = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3].freeze
20
+
21
+ def initialize(addr)
22
+ @addr = addr.downcase
23
+ end
24
+
25
+ def witness
26
+ hrp, data = parse
27
+ raise Sibit::Error, "Invalid Bech32 checksum in '#{@addr}'" unless verified?(hrp, data)
28
+ prog = convert(data[1..-7], 5, 8, false)
29
+ prog.pack('C*').unpack1('H*')
30
+ end
31
+
32
+ def version
33
+ _, data = parse
34
+ data[0]
35
+ end
36
+
37
+ private
38
+
39
+ def parse
40
+ pos = @addr.rindex('1')
41
+ raise Sibit::Error, "Invalid Bech32 address '#{@addr}': no separator" if pos.nil? || pos < 1
42
+ hrp = @addr[0...pos]
43
+ rest = @addr[(pos + 1)..]
44
+ raise Sibit::Error, "Invalid Bech32 address '#{@addr}': data too short" if rest.length < 6
45
+ data = rest.chars.map { |c| CHARSET.index(c) }
46
+ raise Sibit::Error, "Invalid Bech32 character in '#{@addr}'" if data.include?(nil)
47
+ [hrp, data]
48
+ end
49
+
50
+ def verified?(hrp, data)
51
+ chk = polymod(expand(hrp) + data)
52
+ [1, 0x2bc830a3].include?(chk)
53
+ end
54
+
55
+ def expand(hrp)
56
+ hrp.chars.map { |c| c.ord >> 5 } + [0] + hrp.chars.map { |c| c.ord & 31 }
57
+ end
58
+
59
+ def polymod(values)
60
+ chk = 1
61
+ values.each do |v|
62
+ top = chk >> 25
63
+ chk = ((chk & 0x1ffffff) << 5) ^ v
64
+ 5.times { |i| chk ^= GENERATOR[i] if (top >> i).allbits?(1) }
65
+ end
66
+ chk
67
+ end
68
+
69
+ def convert(data, frombits, tobits, pad)
70
+ acc = 0
71
+ bits = 0
72
+ result = []
73
+ maxv = (1 << tobits) - 1
74
+ data.each do |v|
75
+ acc = (acc << frombits) | v
76
+ bits += frombits
77
+ while bits >= tobits
78
+ bits -= tobits
79
+ result << ((acc >> bits) & maxv)
80
+ end
81
+ end
82
+ result << ((acc << (tobits - bits)) & maxv) if pad && bits.positive?
83
+ result
84
+ end
85
+ end
86
+ end
data/lib/sibit/tx.rb CHANGED
@@ -5,6 +5,7 @@
5
5
 
6
6
  require 'digest'
7
7
  require_relative 'base58'
8
+ require_relative 'bech32'
8
9
  require_relative 'key'
9
10
  require_relative 'script'
10
11
 
@@ -98,8 +99,8 @@ class Sibit
98
99
  end
99
100
 
100
101
  def script
101
- hash160 = address_to_hash160(@address)
102
- [0x76, 0xa9, 0x14].pack('C*') + [hash160].pack('H*') + [0x88, 0xac].pack('C*')
102
+ return segwit_script if @address.downcase.start_with?('bc1')
103
+ p2pkh_script
103
104
  end
104
105
 
105
106
  def script_hex
@@ -108,9 +109,17 @@ class Sibit
108
109
 
109
110
  private
110
111
 
111
- def address_to_hash160(addr)
112
- decoded = Base58.new(addr).decode
113
- decoded[2..41]
112
+ def p2pkh_script
113
+ decoded = Base58.new(@address).decode
114
+ hash = decoded[2..41]
115
+ [0x76, 0xa9, 0x14].pack('C*') + [hash].pack('H*') + [0x88, 0xac].pack('C*')
116
+ end
117
+
118
+ def segwit_script
119
+ bech = Bech32.new(@address)
120
+ witness = bech.witness
121
+ len = witness.length / 2
122
+ [0x00, len].pack('C*') + [witness].pack('H*')
114
123
  end
115
124
  end
116
125
 
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.2'
12
+ VERSION = '0.30.3'
13
13
  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.30.2
4
+ version: 0.30.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
@@ -162,6 +162,7 @@ files:
162
162
  - features/support/env.rb
163
163
  - lib/sibit.rb
164
164
  - lib/sibit/base58.rb
165
+ - lib/sibit/bech32.rb
165
166
  - lib/sibit/bestof.rb
166
167
  - lib/sibit/bitcoinchain.rb
167
168
  - lib/sibit/blockchain.rb