bitcoin-ruby 0.0.14 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9bacd4496251a558a0f1eac2b07a9760db13dde1
4
- data.tar.gz: dd2be23dff65df8f413edc45e10b5c8c1dc12743
3
+ metadata.gz: 392936a305872b186484815f8a1c6c91725029d1
4
+ data.tar.gz: f44d55252bf1c614e5679b80113cfd59ca94815e
5
5
  SHA512:
6
- metadata.gz: 429192b346b5c1e9b022787b4b0b9b3201791cba0981aece83092cbbb8297c19a40f0bb7d686c6011cab84d0219e914e5f76e8c8af5fb7512f8b4f3ddbf1b9ed
7
- data.tar.gz: b66dc9ce517c43952554e7eed44dd38d2b96931db305cce6c08e4a742ff5669136e0fd557287e8cce519ed410c60376ea5862b1e9a4592c55778b52324dca2b7
6
+ metadata.gz: 2dab50ef851a4ba5a202099052ce566f86416cfdad002289668d76d109cdc32298fb0f3f99713522dee1d1dfa4bbac0335db3a9f4dd15b53bd7b9daaed9fc633
7
+ data.tar.gz: 06b920e486a56d4c22ad20ac2da62f2d3c89da1a60f561c01e82bf7cf953bc8db9e70bed8de2e01b1517843c72132fe9cc68403624b897bbcbc2cf3845baee86
@@ -1,5 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2.0
4
- - 2.3.2
5
- - 2.4.1
3
+ - 2.2.9
4
+ - 2.3.6
5
+ - 2.4.3
6
+ - 2.5.0
data/COPYING CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2017 Julian Langschaedel <meta.rb@gmail.com>
1
+ Copyright (c) 2018 Julian Langschaedel <meta.rb@gmail.com>
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bitcoin-ruby (0.0.14)
4
+ bitcoin-ruby (0.0.15)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -4,22 +4,13 @@ This is a ruby library for interacting with the bitcoin protocol/network.
4
4
 
5
5
  Some of the main features are:
6
6
 
7
+ * Bitcoin::Key provides a high-level API for creating and handling keys/addresses
7
8
  * Bitcoin::Util provides the basic bitcoin utility functions for base58, ECC, etc.
8
9
  * Bitcoin::Protocol can parse/create all protocol messages
9
10
  * Bitcoin::Script implementation, create/run scripts and verify signatures
10
- * Bitcoin::Key provides a high-level API for creating and handling keys/addresses
11
11
  * Bitcoin::Builder provides a high-level API for creating transactions (and blocks)
12
12
  * Bitcoin::Litecoin implements all the litecoin-specific differences
13
13
 
14
- == Related Projects
15
-
16
- * toshi[https://github.com/coinbase/toshi]
17
- * bitcoin-ruby-blockchain[http://github.com/mhanne/bitcoin-ruby-blockchain]
18
- * bitcoin-ruby-node[http://github.com/mhanne/bitcoin-ruby-node]
19
- * bitcoin-ruby-wallet[http://github.com/mhanne/bitcoin-ruby-wallet]
20
- * bitcoin-ruby-gui[http://github.com/mhanne/bitcoin-ruby-gui]
21
- * namecoin-ruby[http://github.com/mhanne/namecoin-ruby]
22
-
23
14
  == Compatible with...
24
15
 
25
16
  * ruby 1.9.3
@@ -30,13 +21,9 @@ Some of the main features are:
30
21
 
31
22
  == Installation
32
23
 
33
- We assume you already have a ruby 1.9 or 2.0 compatible interpreter and rubygems environment.
34
-
35
- git clone https://github.com/lian/bitcoin-ruby.git; cd bitcoin-ruby
36
-
37
- if you want to have it available system-wide, just build the gem and install it:
38
-
39
- gem build bitcoin-ruby.gemspec && gem install bitcoin-ruby-0.0.11.gem
24
+ gem install bitcoin-ruby
25
+ # OR
26
+ git clone https://github.com/lian/bitcoin-ruby.git; cd bitcoin-ruby; bundle install
40
27
 
41
28
  Note that some aspects of the library (such as networking, storage, etc.) need
42
29
  additional dependencies which are not specified in the gemspec. The core requirements are
@@ -58,18 +45,13 @@ see EXAMPLES.
58
45
 
59
46
  Generate a Bitcoin::Key
60
47
 
61
- key = Bitcoin::generate_key
62
- key #=> [<privkey>, <pubkey>]
63
-
64
- Get the address from a public key
65
-
66
- address = Bitcoin::pubkey_to_address(key[1])
67
- address #=> <bitcoin address>
68
-
69
- Check if an address is valid
70
-
71
- Bitcoin::valid_address?(address) #=> true
72
-
48
+ key = Bitcoin::Key.generate
49
+ key.priv
50
+ key.pub
51
+ key.addr
52
+ sig = key.sign("data")
53
+ key.verify("data", sig)
54
+ recovered_key = Bitcoin::Key.from_base58(key.to_base58)
73
55
 
74
56
  === Blocks / Transactions parsing
75
57
 
@@ -8,6 +8,7 @@ require 'securerandom'
8
8
 
9
9
  module Bitcoin
10
10
 
11
+ autoload :Bech32, 'bitcoin/bech32'
11
12
  autoload :Connection, 'bitcoin/connection'
12
13
  autoload :Protocol, 'bitcoin/protocol'
13
14
  autoload :P, 'bitcoin/protocol'
@@ -58,10 +59,7 @@ module Bitcoin
58
59
  # check if given +address+ is valid.
59
60
  # this means having a correct version byte, length and checksum.
60
61
  def valid_address?(address)
61
- hex = decode_base58(address) rescue nil
62
- return false unless hex && hex.bytesize == 50
63
- return false unless [address_version, p2sh_version].include?(hex[0...2])
64
- address_checksum?(address)
62
+ address_type(address) != nil
65
63
  end
66
64
 
67
65
  # check if given +pubkey+ is valid.
@@ -74,17 +72,42 @@ module Bitcoin
74
72
 
75
73
  # get hash160 for given +address+. returns nil if address is invalid.
76
74
  def hash160_from_address(address)
77
- return nil unless valid_address?(address)
78
- decode_base58(address)[2...42]
75
+ case address_type(address)
76
+ when :witness_v0_keyhash
77
+ _, witness_program_hex = decode_segwit_address(address)
78
+ witness_program_hex
79
+ when :hash160, :p2sh
80
+ decode_base58(address)[2...42]
81
+ end
79
82
  end
80
83
 
81
84
  # get type of given +address+.
82
85
  def address_type(address)
83
- return nil unless valid_address?(address)
84
- case decode_base58(address)[0...2]
85
- when address_version; :hash160
86
- when p2sh_version; :p2sh
86
+ segwit_decoded = decode_segwit_address(address)
87
+ if segwit_decoded
88
+ witness_version, witness_program_hex = segwit_decoded
89
+ witness_program = [witness_program_hex].pack("H*")
90
+
91
+ if witness_version == 0 && witness_program.bytesize == 20
92
+ return :witness_v0_keyhash
93
+ end
94
+
95
+ if witness_version == 0 && witness_program.bytesize == 32
96
+ return :witness_v0_scripthash
97
+ end
98
+ end
99
+
100
+ hex = decode_base58(address) rescue nil
101
+ if hex && hex.bytesize == 50 && address_checksum?(address)
102
+ case hex[0...2]
103
+ when address_version
104
+ return :hash160
105
+ when p2sh_version
106
+ return :p2sh
107
+ end
87
108
  end
109
+
110
+ nil
88
111
  end
89
112
 
90
113
  def sha256(hex)
@@ -113,6 +136,49 @@ module Bitcoin
113
136
  return Bitcoin.hash160_to_p2sh_address(Bitcoin.hash160(redeem_script.hth)), redeem_script
114
137
  end
115
138
 
139
+
140
+ def encode_segwit_address(version, program_hex)
141
+ hrp = Bitcoin.network[:bech32_hrp]
142
+ raise "Invalid network" if hrp.nil?
143
+
144
+ program = [program_hex].pack("H*")
145
+
146
+ return nil if version > 16
147
+ length = program.size
148
+ return nil if version == 0 && length != 20 && length != 32
149
+ return nil if length < 2 || length > 40
150
+
151
+ data = [ version ] + Bitcoin::Bech32.convert_bits(program.unpack("C*"), from_bits: 8, to_bits: 5, pad: true)
152
+
153
+ address = Bitcoin::Bech32.encode(hrp, data)
154
+
155
+ return address.nil? ? nil : address
156
+ end
157
+
158
+ def decode_segwit_address(address)
159
+ hrp = Bitcoin.network[:bech32_hrp]
160
+ return nil if hrp.nil?
161
+
162
+ actual_hrp, data = Bitcoin::Bech32.decode(address)
163
+
164
+ return nil if actual_hrp.nil?
165
+ length = data.size
166
+ return nil if length == 0 || length > 65
167
+ return nil if hrp != actual_hrp
168
+ return nil if data[0] > 16
169
+
170
+
171
+ program = Bitcoin::Bech32.convert_bits(data[1..-1], from_bits: 5, to_bits: 8, pad: false)
172
+ return nil if program.nil?
173
+
174
+ length = program.size
175
+ return nil if length < 2 || length > 40
176
+ return nil if data[0] == 0 && length != 20 && length != 32
177
+
178
+ program_hex = program.pack("C*").unpack("H*").first
179
+ return [data[0], program_hex]
180
+ end
181
+
116
182
  def int_to_base58(int_val, leading_zero_bytes=0)
117
183
  alpha = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
118
184
  base58_val, base = '', alpha.size
@@ -439,7 +505,6 @@ module Bitcoin
439
505
 
440
506
  extend Util
441
507
 
442
-
443
508
  module BinaryExtensions
444
509
  # bin-to-hex
445
510
  def bth; unpack("H*")[0]; end
@@ -557,6 +622,7 @@ module Bitcoin
557
622
  privkey_version: "80",
558
623
  extended_privkey_version: "0488ade4",
559
624
  extended_pubkey_version: "0488b21e",
625
+ bech32_hrp: "bc",
560
626
  default_port: 8333,
561
627
  protocol_version: 70001,
562
628
  coinbase_maturity: 100,
@@ -614,6 +680,7 @@ module Bitcoin
614
680
  privkey_version: "ef",
615
681
  extended_privkey_version: "04358394",
616
682
  extended_pubkey_version: "043587cf",
683
+ bech32_hrp: "tb",
617
684
  default_port: 18333,
618
685
  bip34_height: 21111,
619
686
  dns_seeds: [ ],
@@ -625,6 +692,7 @@ module Bitcoin
625
692
  })
626
693
 
627
694
  NETWORKS[:regtest] = NETWORKS[:testnet].merge({
695
+ bech32_hrp: "bcrt",
628
696
  default_port: 18444,
629
697
  genesis_hash: "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206",
630
698
  proof_of_work_limit: 0x207fffff,
@@ -660,6 +728,7 @@ module Bitcoin
660
728
  address_version: "30",
661
729
  p2sh_version: "32",
662
730
  privkey_version: "b0",
731
+ bech32_hrp: "ltc",
663
732
  extended_privkey_version: "019d9cfe",
664
733
  extended_pubkey_version: "019da462",
665
734
  default_port: 9333,
@@ -710,6 +779,7 @@ module Bitcoin
710
779
  address_version: "6f",
711
780
  p2sh_version: "3a",
712
781
  privkey_version: "ef",
782
+ bech32_hrp: "tltc",
713
783
  extended_privkey_version: "0436ef7d",
714
784
  extended_pubkey_version: "0436f6e1",
715
785
  default_port: 19335,
@@ -733,6 +803,7 @@ module Bitcoin
733
803
  address_version: "1e",
734
804
  p2sh_version: "16",
735
805
  privkey_version: "9e",
806
+ bech32_hrp: nil,
736
807
  extended_privkey_version: "02fac398",
737
808
  extended_pubkey_version: "02facafd",
738
809
  default_port: 22556,
@@ -835,6 +906,7 @@ module Bitcoin
835
906
  project: :namecoin,
836
907
  magic_head: "\xF9\xBE\xB4\xFE",
837
908
  address_version: "34",
909
+ bech32_hrp: nil,
838
910
  default_port: 8334,
839
911
  protocol_version: 35000,
840
912
  min_tx_fee: 50_000,
@@ -0,0 +1,172 @@
1
+ # encoding: ascii-8bit
2
+ # Ruby reference implementation: https://github.com/sipa/bech32/tree/master/ref/c
3
+ module Bitcoin; end
4
+ module Bitcoin::Bech32
5
+
6
+ CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l".unpack("C*")
7
+ CHARSET_REV = [
8
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
9
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
10
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
11
+ 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1,
12
+ -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
13
+ 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1,
14
+ -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
15
+ 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1
16
+ ]
17
+
18
+ class << self
19
+
20
+ def polymod_step(pre)
21
+ b = pre >> 25
22
+ return ((pre & 0x1FFFFFF) << 5) ^ \
23
+ (-((b >> 0) & 1) & 0x3b6a57b2) ^ \
24
+ (-((b >> 1) & 1) & 0x26508e6d) ^ \
25
+ (-((b >> 2) & 1) & 0x1ea119fa) ^ \
26
+ (-((b >> 3) & 1) & 0x3d4233dd) ^ \
27
+ (-((b >> 4) & 1) & 0x2a1462b3)
28
+ end
29
+
30
+ def encode(hrp, data)
31
+ buf = []
32
+ chk = 1
33
+
34
+ hrp.unpack("C*").each do |ch|
35
+ return nil if ch < 33 || ch > 126
36
+ return nil if ch >= 'A'.ord && ch <= 'Z'.ord
37
+ chk = polymod_step(chk) ^ (ch >> 5)
38
+ end
39
+
40
+ return nil if (hrp.bytesize + 7 + data.size) > 90
41
+
42
+ chk = polymod_step(chk)
43
+ hrp.unpack("C*").each do |ch|
44
+ chk = polymod_step(chk) ^ (ch & 0x1f)
45
+ buf << ch
46
+ end
47
+
48
+ buf << '1'.ord
49
+
50
+ data.each do |i|
51
+ return nil if (i >> 5) != 0
52
+ chk = polymod_step(chk) ^ i
53
+ buf << CHARSET[i]
54
+ end
55
+
56
+ 6.times do |n|
57
+ chk = polymod_step(chk)
58
+ end
59
+
60
+ chk ^= 1
61
+
62
+ 6.times do |i|
63
+ buf << CHARSET[(chk >> ((5 - i) * 5)) & 0x1f]
64
+ end
65
+
66
+ return buf.pack("C*")
67
+ end
68
+
69
+ def decode(input)
70
+ chk = 1
71
+ input_len = input.bytesize
72
+ have_lower, have_upper = false, false
73
+
74
+ return nil if input_len < 8 || input_len > 90
75
+
76
+ data_len = 0
77
+ while data_len < input_len && input[(input_len - 1) - data_len] != '1' do
78
+ data_len += 1
79
+ end
80
+
81
+ hrp_len = input_len - (1 + data_len)
82
+ return nil if hrp_len < 1 || data_len < 6
83
+
84
+ data_len -= 6
85
+
86
+ hrp = []
87
+ hrp_len.times do |i|
88
+ ch = input[i].ord
89
+ return nil if ch < 33 || ch > 126
90
+
91
+ if ch >= 'a'.ord && ch <= 'z'.ord
92
+ have_lower = true
93
+ elsif ch >= 'A'.ord && ch <= 'Z'.ord
94
+ have_upper = true
95
+ ch = (ch - 'A'.ord) + 'a'.ord
96
+ end
97
+
98
+ hrp << ch
99
+ chk = polymod_step(chk) ^ (ch >> 5)
100
+ end
101
+
102
+ chk = polymod_step(chk)
103
+
104
+ hrp_len.times do |i|
105
+ chk = polymod_step(chk) ^ (input[i].ord & 0x1f)
106
+ end
107
+
108
+ data = []
109
+ i = hrp_len + 1
110
+ while i < input_len do
111
+ ch = input[i].ord
112
+ v = ((ch & 0x80) != 0) ? -1 : CHARSET_REV[ch]
113
+
114
+ have_lower = true if ch >= 'a'.ord && ch <= 'z'.ord
115
+ have_upper = true if ch >= 'A'.ord && ch <= 'Z'.ord
116
+ return nil if v == -1
117
+
118
+ chk = polymod_step(chk) ^ v
119
+ if (i + 6) < input_len
120
+ data << v
121
+ end
122
+ i += 1
123
+ end
124
+
125
+ return nil if have_lower && have_upper
126
+ return nil if chk != 1
127
+
128
+ return [hrp.pack("C*"), data]
129
+ end
130
+
131
+ # Utility for converting bytes of data between bases. These is used for
132
+ # BIP 173 address encoding/decoding to convert between sequences of bytes
133
+ # representing 8-bit values and groups of 5 bits. Conversions may be padded
134
+ # with trailing 0 bits to the nearest byte boundary. Returns nil if
135
+ # conversion requires padding and pad is false.
136
+ #
137
+ # For example:
138
+ #
139
+ # convert_bits("\xFF\xFF", from_bits: 8, to_bits: 5, pad: true)
140
+ # => "\x1F\x1F\x1F\10"
141
+ #
142
+ # See https://github.com/bitcoin/bitcoin/blob/595a7bab23bc21049526229054ea1fff1a29c0bf/src/utilstrencodings.h#L154
143
+ def convert_bits(chunks, from_bits:, to_bits:, pad:)
144
+ output_mask = (1 << to_bits) - 1
145
+ buffer_mask = (1 << (from_bits + to_bits - 1)) - 1
146
+
147
+ buffer = 0
148
+ bits = 0
149
+
150
+ output = []
151
+ chunks.each do |chunk|
152
+ buffer = ((buffer << from_bits) | chunk) & buffer_mask
153
+ bits += from_bits
154
+ while bits >= to_bits
155
+ bits -= to_bits
156
+ output << ((buffer >> bits) & output_mask)
157
+ end
158
+ end
159
+
160
+ if pad && bits > 0
161
+ output << ((buffer << (to_bits - bits)) & output_mask)
162
+ end
163
+
164
+ if !pad && (bits >= from_bits || ((buffer << (to_bits - bits)) & output_mask) != 0)
165
+ return nil
166
+ end
167
+
168
+ output
169
+ end
170
+
171
+ end
172
+ end