bitcoinrb 0.2.4 → 0.2.5
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/.ruby-version +1 -1
- data/.travis.yml +1 -0
- data/LICENSE.txt +1 -1
- data/README.md +2 -0
- data/lib/bitcoin.rb +4 -0
- data/lib/bitcoin/bit_stream.rb +71 -0
- data/lib/bitcoin/block_filter.rb +83 -0
- data/lib/bitcoin/gcs_filter.rb +135 -0
- data/lib/bitcoin/rpc/request_handler.rb +2 -2
- data/lib/bitcoin/script/script.rb +7 -2
- data/lib/bitcoin/version.rb +1 -1
- data/lib/bitcoin/wallet/base.rb +13 -8
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 895222030c0d0673f1524e112cf42d8cbb8e248558ba356e156a92b7482d4344
|
4
|
+
data.tar.gz: cca9f6a8777925fcf39c47a835549b1894554e2d3c67400ba330487731677a89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cbb089fdfa71ac6a9c60591789c18b78af3fac81e6ba82ac264a50cd1d464b814f8989ca62fdde78910640e241f2b7e8c516b20b9e67eb979efae86c43b9b0ab
|
7
|
+
data.tar.gz: bf0b6f27f6e4819569f3d814194b202f18d829bf315591ce8fa75db0846b2ef372ca45294537918ff7d161b37947f91be05562200d7028bc39b598ec83f01b26
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.6.0
|
data/.travis.yml
CHANGED
data/LICENSE.txt
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c) 2017-
|
3
|
+
Copyright (c) 2017-2019 HAW International, Inc. / chaintope, Inc.
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
@@ -13,7 +13,9 @@ Bitcoinrb supports following feature:
|
|
13
13
|
* De/serialization of Bitcoin protocol network messages
|
14
14
|
* De/serialization of blocks and transactions
|
15
15
|
* Key generation and verification for ECDSA, including [BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) and [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) supports.
|
16
|
+
* ECDSA signature(RFC6979 -Deterministic ECDSA, LOW-S, LOW-R support)
|
16
17
|
* Segwit support (parsing segwit payload, Bech32 address, sign for segwit tx, etc..)
|
18
|
+
* PSBT(Partially Signed Bitcoin Transaction) support
|
17
19
|
* [WIP] SPV node
|
18
20
|
* [WIP] 0ff-chain protocol
|
19
21
|
|
data/lib/bitcoin.rb
CHANGED
@@ -47,6 +47,10 @@ module Bitcoin
|
|
47
47
|
autoload :BloomFilter, 'bitcoin/bloom_filter'
|
48
48
|
autoload :Payments, 'bitcoin/payments'
|
49
49
|
autoload :PSBT, 'bitcoin/psbt'
|
50
|
+
autoload :GCSFilter, 'bitcoin/gcs_filter'
|
51
|
+
autoload :BlockFilter, 'bitcoin/block_filter'
|
52
|
+
autoload :BitStreamWriter, 'bitcoin/bit_stream'
|
53
|
+
autoload :BitStreamReader, 'bitcoin/bit_stream'
|
50
54
|
|
51
55
|
require_relative 'bitcoin/constants'
|
52
56
|
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Bitcoin
|
2
|
+
|
3
|
+
class BitStreamWriter
|
4
|
+
|
5
|
+
MAX_BIT = 2**64
|
6
|
+
|
7
|
+
attr_reader :stream
|
8
|
+
attr_accessor :buffer
|
9
|
+
attr_accessor :offset
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@stream = ''
|
13
|
+
@buffer = 0
|
14
|
+
@offset = 0
|
15
|
+
end
|
16
|
+
|
17
|
+
def write(data, nbits)
|
18
|
+
raise "nbits must be between 0 and 64" if nbits < 0 || nbits > 64
|
19
|
+
while nbits > 0
|
20
|
+
bits = [8 - offset, nbits].min
|
21
|
+
tmp = (data << (64 - nbits)) & 0b1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111
|
22
|
+
self.buffer |= (tmp >> (64 - 8 + offset))
|
23
|
+
self.offset += bits
|
24
|
+
nbits -= bits
|
25
|
+
flush if offset == 8
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def flush
|
30
|
+
return if offset == 0
|
31
|
+
self.stream << [buffer.to_even_length_hex].pack('H*')
|
32
|
+
self.offset = 0
|
33
|
+
self.buffer = 0
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
class BitStreamReader
|
39
|
+
|
40
|
+
attr_reader :stream
|
41
|
+
attr_accessor :buffer
|
42
|
+
attr_accessor :offset
|
43
|
+
|
44
|
+
def initialize(payload)
|
45
|
+
@offset = 8
|
46
|
+
@buffer = 0
|
47
|
+
@stream = StringIO.new(payload)
|
48
|
+
end
|
49
|
+
|
50
|
+
# offset
|
51
|
+
def read(nbits)
|
52
|
+
raise 'nbits must be between 0 and 64' if nbits < 0 || nbits > 64
|
53
|
+
data = 0
|
54
|
+
while nbits > 0
|
55
|
+
if offset == 8
|
56
|
+
self.buffer = stream.read(1).bth.to_i(16)
|
57
|
+
self.offset = 0
|
58
|
+
end
|
59
|
+
bits = [8 - offset, nbits].min
|
60
|
+
data <<= bits
|
61
|
+
tmp = (buffer << offset) & 255
|
62
|
+
data = data | (tmp >> (8 - bits))
|
63
|
+
self.offset += bits
|
64
|
+
nbits -= bits
|
65
|
+
end
|
66
|
+
data
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Bitcoin
|
2
|
+
|
3
|
+
# Compact Block Filter
|
4
|
+
# https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki
|
5
|
+
# This implementation ported the implementation of Bitcoin Core's blockfilter.cpp.
|
6
|
+
# https://github.com/bitcoin/bitcoin/blob/master/src/blockfilter.cpp
|
7
|
+
class BlockFilter
|
8
|
+
|
9
|
+
TYPE = {basic: 0}
|
10
|
+
|
11
|
+
# basic filter params
|
12
|
+
BASIC_FILTER_P = 19
|
13
|
+
BASIC_FILTER_M = 784931
|
14
|
+
|
15
|
+
attr_accessor :filter_type
|
16
|
+
attr_accessor :filter
|
17
|
+
attr_accessor :block_hash
|
18
|
+
|
19
|
+
# Constructor
|
20
|
+
# @param [Integer] filter_type
|
21
|
+
# @param [Bitcoin::GCSFilter] filter a GCS filter.
|
22
|
+
# @param [String] block_hash a block hash with hex format.
|
23
|
+
# @return [Bitcoin::BlockFilter]
|
24
|
+
def initialize(filter_type, filter, block_hash)
|
25
|
+
@filter_type = filter_type
|
26
|
+
@filter = filter
|
27
|
+
@block_hash = block_hash
|
28
|
+
end
|
29
|
+
|
30
|
+
# Build BlockFilter from the block data.
|
31
|
+
# @param [Integer] filter_type a filter type(basic or extended).
|
32
|
+
# @param [Bitcoin::Block] block target block object.
|
33
|
+
# @param [Array[Bitcoin::Script]] prev_out_scripts The previous output script (the script being spent) for each input, except for the coinbase transaction.
|
34
|
+
# @return [Bitcoin::BlockFilter] block filter object.
|
35
|
+
def self.build_from_block(filter_type, block, prev_out_scripts)
|
36
|
+
block_hash = block.block_hash.htb[0...16]
|
37
|
+
filter = case filter_type
|
38
|
+
when TYPE[:basic]
|
39
|
+
GCSFilter.new(block_hash, BASIC_FILTER_P, BASIC_FILTER_M, elements: build_basic_filter_elements(block, prev_out_scripts))
|
40
|
+
else
|
41
|
+
raise "unknown filter type: #{filter_type}."
|
42
|
+
end
|
43
|
+
BlockFilter.new(filter_type, filter, block.block_hash)
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# calculate filter hash.
|
48
|
+
# @return [String] this filter hash with hex format.
|
49
|
+
def filter_hash
|
50
|
+
Bitcoin.double_sha256(encoded_filter.htb).bth
|
51
|
+
end
|
52
|
+
|
53
|
+
# calculate filter header which calculates from previous filter header and current filter hash.
|
54
|
+
# @param [String] prev_header a previous header with hex format.
|
55
|
+
# @return [String] header of this filter with hex format.
|
56
|
+
def header(prev_header)
|
57
|
+
Bitcoin.double_sha256(filter_hash.htb + prev_header.htb).bth
|
58
|
+
end
|
59
|
+
|
60
|
+
# get encoded filter.
|
61
|
+
def encoded_filter
|
62
|
+
filter.encoded
|
63
|
+
end
|
64
|
+
|
65
|
+
# build basic filter elements
|
66
|
+
# @param [Bitcoin::Block] block current block
|
67
|
+
# @param [Array[Bitcoin::Script]] prev_out_scripts The previous output script (the script being spent) for each input, except for the coinbase transaction.
|
68
|
+
# @return [Array[String]] basic filter elements
|
69
|
+
def self.build_basic_filter_elements(block, prev_out_scripts)
|
70
|
+
elements = []
|
71
|
+
block.transactions.each do |tx|
|
72
|
+
elements += tx.outputs.select{|o|
|
73
|
+
!o.script_pubkey.empty? && !o.script_pubkey.op_return?}.map{|o| o.script_pubkey.to_payload}
|
74
|
+
end
|
75
|
+
elements += prev_out_scripts.select{|s|!s.empty? && !s.op_return?}.map(&:to_payload)
|
76
|
+
elements.uniq
|
77
|
+
end
|
78
|
+
|
79
|
+
private_class_method :build_basic_filter_elements
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'siphash'
|
2
|
+
|
3
|
+
module Bitcoin
|
4
|
+
|
5
|
+
# Golomb-coded set filter
|
6
|
+
# see https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki
|
7
|
+
class GCSFilter
|
8
|
+
|
9
|
+
attr_reader :p # Golomb-Rice coding parameter
|
10
|
+
attr_reader :m # Inverse false positive rate
|
11
|
+
attr_reader :n # Number of elements in the filter
|
12
|
+
attr_reader :key # SipHash key
|
13
|
+
attr_reader :encoded # encoded filter with hex format.
|
14
|
+
|
15
|
+
# initialize Filter object.
|
16
|
+
# @param [String] key the 128-bit key used to randomize the SipHash outputs.
|
17
|
+
# @param [Integer] p the bit parameter of the Golomb-Rice coding.
|
18
|
+
# @param [Integer] m which determines the false positive rate.
|
19
|
+
# @param [Array] elements the filter elements.
|
20
|
+
# @param [String] encoded_filter encoded filter with hex format.
|
21
|
+
# @return [Bitcoin::GCSFilter]
|
22
|
+
def initialize(key, p, m, elements: nil, encoded_filter: nil)
|
23
|
+
raise 'specify either elements or encoded_filter.' if elements.nil? && encoded_filter.nil?
|
24
|
+
raise 'p must be <= 32' if p > 32
|
25
|
+
@key = key
|
26
|
+
@p = p
|
27
|
+
@m = m
|
28
|
+
if elements
|
29
|
+
raise 'elements size must be < 2**32.' if elements.size >= (2**32)
|
30
|
+
@n = elements.size
|
31
|
+
encoded = Bitcoin.pack_var_int(@n)
|
32
|
+
bit_writer = Bitcoin::BitStreamWriter.new
|
33
|
+
unless elements.empty?
|
34
|
+
last_value = 0
|
35
|
+
hashed_set = elements.map{|e| hash_to_range(e) }.sort
|
36
|
+
hashed_set.each do |v|
|
37
|
+
delta = v - last_value
|
38
|
+
golomb_rice_encode(bit_writer, p, delta)
|
39
|
+
last_value = v
|
40
|
+
end
|
41
|
+
end
|
42
|
+
bit_writer.flush
|
43
|
+
encoded << bit_writer.stream
|
44
|
+
@encoded = encoded.bth
|
45
|
+
else
|
46
|
+
@encoded = encoded_filter
|
47
|
+
@n, payload = Bitcoin.unpack_var_int(encoded_filter.htb)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Range of element hashes, F = N * M
|
52
|
+
def f
|
53
|
+
n * m
|
54
|
+
end
|
55
|
+
|
56
|
+
# Hash a data element to an integer in the range [0, F).
|
57
|
+
# @param [String] element with binary format.
|
58
|
+
# @return [Integer]
|
59
|
+
def hash_to_range(element)
|
60
|
+
hash = SipHash.digest(key, element)
|
61
|
+
map_into_range(hash, f)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Checks if the element may be in the set. False positives are possible with probability 1/M.
|
65
|
+
# @param [String] element with binary format
|
66
|
+
# @return [Boolean] whether element in set.
|
67
|
+
def match?(element)
|
68
|
+
query = hash_to_range(element)
|
69
|
+
match_internal?([query], 1)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Checks if any of the given elements may be in the set. False positives are possible with probability 1/M per element checked.
|
73
|
+
# This is more efficient that checking Match on multiple elements separately.
|
74
|
+
# @param [Array] elements list of elements with binary format.
|
75
|
+
# @return [Boolean] whether element in set.
|
76
|
+
def match_any?(elements)
|
77
|
+
queries = elements.map{|e| hash_to_range(e) }.sort
|
78
|
+
match_internal?(queries, queries.size)
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
# hash are then mapped uniformly over the desired range by multiplying with F and taking the top 64 bits of the 128-bit result.
|
84
|
+
# https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
|
85
|
+
# https://stackoverflow.com/a/26855440
|
86
|
+
def map_into_range(x, y)
|
87
|
+
(x * y) >> 64
|
88
|
+
end
|
89
|
+
|
90
|
+
# Checks if the elements may be in the set.
|
91
|
+
# @param [Array[Integer]] hashes the query hash list.
|
92
|
+
# @param [Integer] size query size.
|
93
|
+
# @return [Boolean] whether elements in set.
|
94
|
+
def match_internal?(hashes, size)
|
95
|
+
n, payload = Bitcoin.unpack_var_int(encoded.htb)
|
96
|
+
bit_reader = Bitcoin::BitStreamReader.new(payload)
|
97
|
+
value = 0
|
98
|
+
hashes_index = 0
|
99
|
+
n.times do
|
100
|
+
delta = golomb_rice_decode(bit_reader, p)
|
101
|
+
value += delta
|
102
|
+
loop do
|
103
|
+
return false if hashes_index == size
|
104
|
+
return true if hashes[hashes_index] == value
|
105
|
+
break if hashes[hashes_index] > value
|
106
|
+
hashes_index += 1
|
107
|
+
end
|
108
|
+
end
|
109
|
+
false
|
110
|
+
end
|
111
|
+
|
112
|
+
# encode golomb rice
|
113
|
+
def golomb_rice_encode(bit_writer, p, x)
|
114
|
+
q = x >> p
|
115
|
+
while q > 0
|
116
|
+
nbits = q <= 64 ? q : 64
|
117
|
+
bit_writer.write(-1, nbits) # 18446744073709551615 is 2**64 - 1 = ~0ULL in cpp.
|
118
|
+
q -= nbits
|
119
|
+
end
|
120
|
+
bit_writer.write(0, 1)
|
121
|
+
bit_writer.write(x, p)
|
122
|
+
end
|
123
|
+
|
124
|
+
# decode golomb rice
|
125
|
+
def golomb_rice_decode(bit_reader, p)
|
126
|
+
q = 0
|
127
|
+
while bit_reader.read(1) == 1
|
128
|
+
q +=1
|
129
|
+
end
|
130
|
+
r = bit_reader.read(p)
|
131
|
+
(q << p) + r
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
end
|
@@ -105,14 +105,14 @@ module Bitcoin
|
|
105
105
|
# wallet api
|
106
106
|
|
107
107
|
# create wallet
|
108
|
-
def createwallet(wallet_id = 1, wallet_path_prefix = Bitcoin::Wallet::Base
|
108
|
+
def createwallet(wallet_id = 1, wallet_path_prefix = Bitcoin::Wallet::Base.default_path_prefix)
|
109
109
|
wallet = Bitcoin::Wallet::Base.create(wallet_id, wallet_path_prefix)
|
110
110
|
node.wallet = wallet unless node.wallet
|
111
111
|
{wallet_id: wallet.wallet_id, mnemonic: wallet.master_key.mnemonic}
|
112
112
|
end
|
113
113
|
|
114
114
|
# get wallet list.
|
115
|
-
def listwallets(wallet_path_prefix = Bitcoin::Wallet::Base
|
115
|
+
def listwallets(wallet_path_prefix = Bitcoin::Wallet::Base.default_path_prefix)
|
116
116
|
Bitcoin::Wallet::Base.wallet_paths(wallet_path_prefix)
|
117
117
|
end
|
118
118
|
|
@@ -130,7 +130,11 @@ module Bitcoin
|
|
130
130
|
end
|
131
131
|
end
|
132
132
|
else
|
133
|
-
|
133
|
+
if Opcodes.defined?(opcode.ord)
|
134
|
+
s << opcode.ord
|
135
|
+
else
|
136
|
+
s.chunks << (opcode + buf.read) # If opcode is invalid, put all remaining data in last chunk.
|
137
|
+
end
|
134
138
|
end
|
135
139
|
end
|
136
140
|
s
|
@@ -331,7 +335,8 @@ module Bitcoin
|
|
331
335
|
end
|
332
336
|
end
|
333
337
|
else
|
334
|
-
Opcodes.opcode_to_name(c.ord)
|
338
|
+
opcode = Opcodes.opcode_to_name(c.ord)
|
339
|
+
opcode ? opcode : 'OP_UNKNOWN [error]'
|
335
340
|
end
|
336
341
|
end
|
337
342
|
}.join(' ')
|
data/lib/bitcoin/version.rb
CHANGED
data/lib/bitcoin/wallet/base.rb
CHANGED
@@ -8,15 +8,19 @@ module Bitcoin
|
|
8
8
|
attr_reader :db
|
9
9
|
attr_reader :path
|
10
10
|
|
11
|
-
DEFAULT_PATH_PREFIX = "#{Bitcoin.base_dir}/db/wallet/"
|
12
11
|
VERSION = 1
|
13
12
|
|
13
|
+
# get wallet dir path
|
14
|
+
def self.default_path_prefix
|
15
|
+
"#{Bitcoin.base_dir}/db/wallet/"
|
16
|
+
end
|
17
|
+
|
14
18
|
# Create new wallet. If wallet already exist, throw error.
|
15
19
|
# The wallet generates a seed using SecureRandom and store to db at initialization.
|
16
20
|
# @param [String] wallet_id new wallet id.
|
17
21
|
# @param [String] path_prefix wallet file path prefix.
|
18
22
|
# @return [Bitcoin::Wallet::Base] the wallet
|
19
|
-
def self.create(wallet_id = 1, path_prefix =
|
23
|
+
def self.create(wallet_id = 1, path_prefix = default_path_prefix)
|
20
24
|
raise ArgumentError, "wallet_id : #{wallet_id} already exist." if self.exist?(wallet_id, path_prefix)
|
21
25
|
w = self.new(wallet_id, path_prefix)
|
22
26
|
# generate seed
|
@@ -29,23 +33,24 @@ module Bitcoin
|
|
29
33
|
|
30
34
|
# load wallet with specified +wallet_id+
|
31
35
|
# @return [Bitcoin::Wallet::Base] the wallet
|
32
|
-
def self.load(wallet_id, path_prefix =
|
36
|
+
def self.load(wallet_id, path_prefix = default_path_prefix)
|
33
37
|
raise ArgumentError, "wallet_id : #{wallet_id} dose not exist." unless self.exist?(wallet_id, path_prefix)
|
34
38
|
self.new(wallet_id, path_prefix)
|
35
39
|
end
|
36
40
|
|
37
41
|
# get wallets path
|
38
42
|
# @return [Array] Array of paths for each wallet dir.
|
39
|
-
def self.wallet_paths(path_prefix =
|
43
|
+
def self.wallet_paths(path_prefix = default_path_prefix)
|
40
44
|
Dir.glob("#{path_prefix}wallet*/").sort
|
41
45
|
end
|
42
46
|
|
43
47
|
# get current wallet
|
44
|
-
def self.current_wallet(path_prefix =
|
45
|
-
path = wallet_paths.first # TODO default wallet selection
|
48
|
+
def self.current_wallet(path_prefix = default_path_prefix)
|
49
|
+
path = wallet_paths(path_prefix).first # TODO default wallet selection
|
46
50
|
return nil unless path
|
47
|
-
|
48
|
-
|
51
|
+
path.slice!(path_prefix + 'wallet')
|
52
|
+
path.slice!('/')
|
53
|
+
self.load(path.to_i, path_prefix)
|
49
54
|
end
|
50
55
|
|
51
56
|
# get account list based on BIP-44
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bitcoinrb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- azuchi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ecdsa
|
@@ -303,7 +303,9 @@ files:
|
|
303
303
|
- exe/bitcoinrbd
|
304
304
|
- lib/bitcoin.rb
|
305
305
|
- lib/bitcoin/base58.rb
|
306
|
+
- lib/bitcoin/bit_stream.rb
|
306
307
|
- lib/bitcoin/block.rb
|
308
|
+
- lib/bitcoin/block_filter.rb
|
307
309
|
- lib/bitcoin/block_header.rb
|
308
310
|
- lib/bitcoin/bloom_filter.rb
|
309
311
|
- lib/bitcoin/chain_params.rb
|
@@ -312,6 +314,7 @@ files:
|
|
312
314
|
- lib/bitcoin/chainparams/testnet.yml
|
313
315
|
- lib/bitcoin/constants.rb
|
314
316
|
- lib/bitcoin/ext_key.rb
|
317
|
+
- lib/bitcoin/gcs_filter.rb
|
315
318
|
- lib/bitcoin/key.rb
|
316
319
|
- lib/bitcoin/logger.rb
|
317
320
|
- lib/bitcoin/merkle_tree.rb
|
@@ -436,8 +439,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
436
439
|
- !ruby/object:Gem::Version
|
437
440
|
version: '0'
|
438
441
|
requirements: []
|
439
|
-
|
440
|
-
rubygems_version: 2.7.8
|
442
|
+
rubygems_version: 3.0.1
|
441
443
|
signing_key:
|
442
444
|
specification_version: 4
|
443
445
|
summary: "[WIP]The implementation of Bitcoin Protocol for Ruby."
|