bitcoinrb 1.12.0 → 1.12.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 +4 -4
- data/.github/workflows/ruby.yml +1 -1
- data/bitcoinrb.gemspec +1 -6
- data/lib/bitcoin/bip324/fs_chacha20.rb +3 -5
- data/lib/bitcoin/bip324/fs_chacha_poly1305.rb +19 -17
- data/lib/bitcoin/bip324.rb +1 -1
- data/lib/bitcoin/descriptor/expression.rb +2 -2
- data/lib/bitcoin/descriptor/sp.rb +219 -0
- data/lib/bitcoin/descriptor.rb +20 -0
- data/lib/bitcoin/ext_key.rb +3 -3
- data/lib/bitcoin/message/ping.rb +4 -2
- data/lib/bitcoin/message/version.rb +1 -1
- data/lib/bitcoin/message_sign.rb +98 -38
- data/lib/bitcoin/rpc.rb +0 -2
- data/lib/bitcoin/silent_payment/output.rb +46 -0
- data/lib/bitcoin/silent_payment.rb +113 -12
- data/lib/bitcoin/util.rb +2 -2
- data/lib/bitcoin/version.rb +1 -1
- data/lib/bitcoin.rb +0 -6
- metadata +18 -108
- data/exe/bitcoinrb-cli +0 -5
- data/exe/bitcoinrbd +0 -46
- data/lib/bitcoin/network/connection.rb +0 -73
- data/lib/bitcoin/network/message_handler.rb +0 -243
- data/lib/bitcoin/network/peer.rb +0 -228
- data/lib/bitcoin/network/peer_discovery.rb +0 -42
- data/lib/bitcoin/network/pool.rb +0 -135
- data/lib/bitcoin/network.rb +0 -13
- data/lib/bitcoin/node/cli.rb +0 -122
- data/lib/bitcoin/node/configuration.rb +0 -40
- data/lib/bitcoin/node/spv.rb +0 -87
- data/lib/bitcoin/node.rb +0 -7
- data/lib/bitcoin/rpc/http_server.rb +0 -84
- data/lib/bitcoin/rpc/request_handler.rb +0 -150
- data/lib/bitcoin/store/chain_entry.rb +0 -68
- data/lib/bitcoin/store/db/level_db.rb +0 -98
- data/lib/bitcoin/store/db.rb +0 -9
- data/lib/bitcoin/store/spv_chain.rb +0 -101
- data/lib/bitcoin/store/utxo_db.rb +0 -226
- data/lib/bitcoin/store.rb +0 -12
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
module Bitcoin
|
|
2
|
+
module SilentPayment
|
|
3
|
+
# Represents a detected silent payment output.
|
|
4
|
+
class Output
|
|
5
|
+
# @return [Bitcoin::TxOut] The detected transaction output.
|
|
6
|
+
attr_reader :tx_out
|
|
7
|
+
|
|
8
|
+
# @return [String] The tweak value (t_k) used to derive the output key (32 bytes binary).
|
|
9
|
+
attr_reader :tweak
|
|
10
|
+
|
|
11
|
+
# @return [Integer, nil] The label used for this output, or nil if no label was used.
|
|
12
|
+
attr_reader :label
|
|
13
|
+
|
|
14
|
+
# @param [Bitcoin::TxOut] tx_out The detected transaction output.
|
|
15
|
+
# @param [String] tweak The tweak value (t_k) as 32 bytes binary.
|
|
16
|
+
# @param [Integer, nil] label The label integer, or nil if no label was used.
|
|
17
|
+
# @raise [ArgumentError] If any parameter has an invalid type.
|
|
18
|
+
def initialize(tx_out, tweak, label = nil)
|
|
19
|
+
raise ArgumentError, "tx_out must be a Bitcoin::TxOut." unless tx_out.is_a?(Bitcoin::TxOut)
|
|
20
|
+
raise ArgumentError, "tweak must be a 32-byte String." unless tweak.is_a?(String) && tweak.bytesize == 32
|
|
21
|
+
raise ArgumentError, "label must be an Integer or nil." unless label.nil? || label.is_a?(Integer)
|
|
22
|
+
@tx_out = tx_out
|
|
23
|
+
@tweak = tweak
|
|
24
|
+
@label = label
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Returns the x-only public key of the output.
|
|
28
|
+
# @return [String] The x-only public key as hex string.
|
|
29
|
+
def pubkey
|
|
30
|
+
tx_out.script_pubkey.witness_data[1].bth
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Returns the tweak as hex string.
|
|
34
|
+
# @return [String] The tweak value as hex string.
|
|
35
|
+
def tweak_hex
|
|
36
|
+
tweak.bth
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Returns whether this output was detected using a label.
|
|
40
|
+
# @return [Boolean]
|
|
41
|
+
def labeled?
|
|
42
|
+
!label.nil?
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -1,12 +1,22 @@
|
|
|
1
|
+
require 'set'
|
|
2
|
+
|
|
1
3
|
module Bitcoin
|
|
4
|
+
# BIP-352 silent payment module.
|
|
5
|
+
# @see https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki
|
|
2
6
|
module SilentPayment
|
|
7
|
+
autoload :Output, 'bitcoin/silent_payment/output'
|
|
3
8
|
|
|
4
|
-
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
#
|
|
9
|
+
# Maximum number of silent payment addresses that can share the same scan public key
|
|
10
|
+
# within a single transaction. This is the maximum number of P2TR outputs that can fit
|
|
11
|
+
# within a 100KB transaction under current standardness rules.
|
|
12
|
+
K_MAX = 2323
|
|
13
|
+
|
|
14
|
+
# Derive payment point.
|
|
15
|
+
#
|
|
16
|
+
# @param [Array<Bitcoin::Script>] prevouts An array of previous output script.
|
|
17
|
+
# @param [Array<Bitcoin::Key>] private_keys An array of Bitcoin::Key objects corresponding to each public key in prevouts.
|
|
18
|
+
# @param [Array<Bech32::SilentPaymentAddr>] recipients
|
|
19
|
+
# @return [Array<ECDSA::Point>] An array of derived points.
|
|
10
20
|
# @raise [ArgumentError]
|
|
11
21
|
def derive_payment_points(prevouts, private_keys, recipients)
|
|
12
22
|
raise ArgumentError, "prevouts must be Array." unless prevouts.is_a? Array
|
|
@@ -14,19 +24,19 @@ module Bitcoin
|
|
|
14
24
|
raise ArgumentError, "prevouts and private_keys must be the same length." unless prevouts.length == private_keys.length
|
|
15
25
|
raise ArgumentError, "recipients must be Array." unless recipients.is_a? Array
|
|
16
26
|
|
|
17
|
-
outpoint_l = inputs.map{|i|i.out_point.to_hex}.sort.first
|
|
18
|
-
|
|
19
27
|
input_pub_keys = []
|
|
20
28
|
field = ECDSA::PrimeField.new(Bitcoin::Secp256k1::GROUP.order)
|
|
21
29
|
sum_priv_keys = 0
|
|
22
30
|
prevouts.each_with_index do |prevout, index|
|
|
23
|
-
|
|
31
|
+
key = private_keys[index]
|
|
32
|
+
raise ArgumentError, "private_keys element must be Bitcoin::Key." unless key.is_a? Bitcoin::Key
|
|
33
|
+
priv_key_int = key.priv_key.to_i(16)
|
|
24
34
|
public_key = extract_public_key(prevout, inputs[index])
|
|
25
35
|
next if public_key.nil?
|
|
26
|
-
private_key = if public_key.p2tr? &&
|
|
27
|
-
field.mod(-
|
|
36
|
+
private_key = if public_key.p2tr? && key.to_point.y.odd?
|
|
37
|
+
field.mod(-priv_key_int)
|
|
28
38
|
else
|
|
29
|
-
|
|
39
|
+
priv_key_int
|
|
30
40
|
end
|
|
31
41
|
input_pub_keys << public_key
|
|
32
42
|
sum_priv_keys = field.mod(sum_priv_keys + private_key)
|
|
@@ -34,6 +44,8 @@ module Bitcoin
|
|
|
34
44
|
agg_pubkey = (Bitcoin::Secp256k1::GROUP.generator.to_jacobian * sum_priv_keys).to_affine
|
|
35
45
|
return [] if agg_pubkey.infinity?
|
|
36
46
|
|
|
47
|
+
outpoint_l = inputs.map{|i|i.out_point.to_hex}.sort.first
|
|
48
|
+
|
|
37
49
|
input_hash = Bitcoin.tagged_hash("BIP0352/Inputs", outpoint_l.htb + agg_pubkey.to_hex.htb).bth
|
|
38
50
|
|
|
39
51
|
destinations = {}
|
|
@@ -42,6 +54,12 @@ module Bitcoin
|
|
|
42
54
|
destinations[sp_addr.scan_key] = [] unless destinations.has_key?(sp_addr.scan_key)
|
|
43
55
|
destinations[sp_addr.scan_key] << sp_addr.spend_key
|
|
44
56
|
end
|
|
57
|
+
|
|
58
|
+
# Check K_max limit: fail if any group exceeds the limit
|
|
59
|
+
destinations.each_value do |spends|
|
|
60
|
+
raise ArgumentError, "Recipient group exceeds K_max limit (#{K_MAX})." if spends.length > K_MAX
|
|
61
|
+
end
|
|
62
|
+
|
|
45
63
|
outputs = []
|
|
46
64
|
destinations.each do |scan_key, spends|
|
|
47
65
|
scan_key = Bitcoin::Key.new(pubkey: scan_key).to_point.to_jacobian
|
|
@@ -55,6 +73,89 @@ module Bitcoin
|
|
|
55
73
|
outputs
|
|
56
74
|
end
|
|
57
75
|
|
|
76
|
+
|
|
77
|
+
# Scan transaction outputs for silent payment outputs belonging to the receiver.
|
|
78
|
+
#
|
|
79
|
+
# @param [Array<Bitcoin::Script>] prevouts An array of previous output scripts corresponding to each input.
|
|
80
|
+
# @param [Bitcoin::Key] scan_private_key The receiver's scan private key (b_scan).
|
|
81
|
+
# @param [Bitcoin::Key] spend_pubkey The receiver's spend key. Pass a Key initialized with spend_priv_key to derive the public key.
|
|
82
|
+
# @param [Array<Integer>] labels An array of label integers for labeled addresses (default: []).
|
|
83
|
+
# @return [Array<Bitcoin::SilentPayment::Output>] An array of detected silent payment outputs.
|
|
84
|
+
# @raise [ArgumentError] If any of the required parameters are invalid.
|
|
85
|
+
def scan_sp_outputs(prevouts, scan_private_key, spend_pubkey, labels = [])
|
|
86
|
+
raise ArgumentError, "prevouts must be Array." unless prevouts.is_a? Array
|
|
87
|
+
raise ArgumentError, "scan_private_key must be Bitcoin::Key." unless scan_private_key.is_a? Bitcoin::Key
|
|
88
|
+
raise ArgumentError, "spend_pubkey must be Bitcoin::Key." unless spend_pubkey.is_a? Bitcoin::Key
|
|
89
|
+
|
|
90
|
+
has_taproot = !outputs.find{|o| o.script_pubkey.p2tr? }.nil?
|
|
91
|
+
return [] unless has_taproot
|
|
92
|
+
sum_pub_keys = Bitcoin::Secp256k1::GROUP.infinity.to_jacobian
|
|
93
|
+
maximum_witness_version = Bitcoin::Opcodes.opcode_to_small_int(Bitcoin::Opcodes::OP_1)
|
|
94
|
+
prevouts.each.with_index do |prevout, index|
|
|
95
|
+
return [] if prevout.witness_program? && prevout.witness_data.first > maximum_witness_version
|
|
96
|
+
|
|
97
|
+
public_key = extract_public_key(prevout, inputs[index])
|
|
98
|
+
next if public_key.nil?
|
|
99
|
+
sum_pub_keys += public_key.to_point.to_jacobian
|
|
100
|
+
end
|
|
101
|
+
return [] if sum_pub_keys.infinity?
|
|
102
|
+
|
|
103
|
+
field = ECDSA::PrimeField.new(Bitcoin::Secp256k1::GROUP.order)
|
|
104
|
+
outpoint_l = inputs.map{|i|i.out_point.to_hex}.sort.first
|
|
105
|
+
input_hash = Bitcoin.tagged_hash("BIP0352/Inputs", outpoint_l.htb + sum_pub_keys.to_affine.to_hex.htb).bth
|
|
106
|
+
ecdh_shared_secret = (sum_pub_keys * field.mod(input_hash.to_i(16) * scan_private_key.priv_key.to_i(16))).to_affine.to_hex.htb
|
|
107
|
+
|
|
108
|
+
# Pre-compute label tweak points with their label values and scalar tweaks
|
|
109
|
+
label_tweaks = labels.map do |m|
|
|
110
|
+
label_tweak = Bitcoin.tagged_hash('BIP0352/Label', scan_private_key.priv_key.htb + [m].pack('N'))
|
|
111
|
+
label_point = Bitcoin::Secp256k1::GROUP.generator.to_jacobian * label_tweak.bti
|
|
112
|
+
[m, label_tweak, label_point]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
k = 0
|
|
116
|
+
results = []
|
|
117
|
+
found_outputs = Set.new
|
|
118
|
+
loop do
|
|
119
|
+
# Stop scanning if K_max limit is reached
|
|
120
|
+
break if k == K_MAX
|
|
121
|
+
|
|
122
|
+
t_k = Bitcoin.tagged_hash('BIP0352/SharedSecret', ecdh_shared_secret + [k].pack('N'))
|
|
123
|
+
p_k = Bitcoin::Secp256k1::GROUP.generator.to_jacobian * t_k.bti + spend_pubkey.to_point.to_jacobian
|
|
124
|
+
found = false
|
|
125
|
+
outputs.each do |output|
|
|
126
|
+
next unless output.script_pubkey.p2tr?
|
|
127
|
+
next if found_outputs.include?(output)
|
|
128
|
+
output_pubkey = Bitcoin::Key.from_xonly_pubkey(output.script_pubkey.witness_data[1].bth)
|
|
129
|
+
|
|
130
|
+
# Check basic match (no label)
|
|
131
|
+
if p_k.to_affine.x == output_pubkey.to_point.x
|
|
132
|
+
results << SilentPayment::Output.new(output, t_k)
|
|
133
|
+
found_outputs << output
|
|
134
|
+
k += 1
|
|
135
|
+
found = true
|
|
136
|
+
break
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Check labeled matches
|
|
140
|
+
label_tweaks.each do |label_value, label_tweak_scalar, label_point|
|
|
141
|
+
p_k_labeled = p_k + label_point
|
|
142
|
+
if p_k_labeled.to_affine.x == output_pubkey.to_point.x
|
|
143
|
+
# Full tweak is t_k + label_tweak (mod order)
|
|
144
|
+
full_tweak = field.mod(t_k.bti + label_tweak_scalar.bti).to_s(16).rjust(64, '0').htb
|
|
145
|
+
results << SilentPayment::Output.new(output, full_tweak, label_value)
|
|
146
|
+
found_outputs << output
|
|
147
|
+
k += 1
|
|
148
|
+
found = true
|
|
149
|
+
break
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
break if found
|
|
153
|
+
end
|
|
154
|
+
break unless found
|
|
155
|
+
end
|
|
156
|
+
results
|
|
157
|
+
end
|
|
158
|
+
|
|
58
159
|
# Extract public keys from +prevout+ and input.
|
|
59
160
|
def extract_public_key(prevout, input)
|
|
60
161
|
if prevout.p2pkh?
|
data/lib/bitcoin/util.rb
CHANGED
|
@@ -14,7 +14,7 @@ module Bitcoin
|
|
|
14
14
|
|
|
15
15
|
def unpack_var_string(payload)
|
|
16
16
|
size, payload = unpack_var_int(payload)
|
|
17
|
-
size > 0 ? payload.unpack("a#{size}a*") : [
|
|
17
|
+
size && size > 0 ? payload.unpack("a#{size}a*") : ['', payload.to_s]
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def pack_var_int(i)
|
|
@@ -102,7 +102,7 @@ module Bitcoin
|
|
|
102
102
|
# @return [String] the hash value with binary format.
|
|
103
103
|
def tagged_hash(tag, msg)
|
|
104
104
|
tag_hash = Digest::SHA256.digest(tag)
|
|
105
|
-
Digest::SHA256.digest(tag_hash + tag_hash + msg)
|
|
105
|
+
Digest::SHA256.digest(tag_hash + tag_hash + msg.b)
|
|
106
106
|
end
|
|
107
107
|
|
|
108
108
|
# encode Base58 check address.
|
data/lib/bitcoin/version.rb
CHANGED
data/lib/bitcoin.rb
CHANGED
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
# https://github.com/lian/bitcoin-ruby/blob/master/COPYING
|
|
3
3
|
|
|
4
4
|
require 'bitcoin/version'
|
|
5
|
-
require 'eventmachine'
|
|
6
5
|
require 'schnorr'
|
|
7
6
|
require 'securerandom'
|
|
8
7
|
require 'json'
|
|
9
8
|
require 'bech32'
|
|
10
9
|
require 'base64'
|
|
11
|
-
require 'observer'
|
|
12
10
|
require 'tmpdir'
|
|
13
11
|
require 'merkle'
|
|
14
12
|
|
|
@@ -36,13 +34,10 @@ module Bitcoin
|
|
|
36
34
|
autoload :ExtKey, 'bitcoin/ext_key'
|
|
37
35
|
autoload :ExtPubkey, 'bitcoin/ext_key'
|
|
38
36
|
autoload :Opcodes, 'bitcoin/opcodes'
|
|
39
|
-
autoload :Node, 'bitcoin/node'
|
|
40
37
|
autoload :Base58, 'bitcoin/base58'
|
|
41
38
|
autoload :Secp256k1, 'bitcoin/secp256k1'
|
|
42
39
|
autoload :Mnemonic, 'bitcoin/mnemonic'
|
|
43
40
|
autoload :ValidationState, 'bitcoin/validation'
|
|
44
|
-
autoload :Network, 'bitcoin/network'
|
|
45
|
-
autoload :Store, 'bitcoin/store'
|
|
46
41
|
autoload :RPC, 'bitcoin/rpc'
|
|
47
42
|
autoload :Wallet, 'bitcoin/wallet'
|
|
48
43
|
autoload :BloomFilter, 'bitcoin/bloom_filter'
|
|
@@ -64,7 +59,6 @@ module Bitcoin
|
|
|
64
59
|
autoload :SilentPayment, 'bitcoin/silent_payment'
|
|
65
60
|
autoload :BIP324, 'bitcoin/bip324'
|
|
66
61
|
autoload :BIP321URI, 'bitcoin/bip321_uri'
|
|
67
|
-
autoload :BIP353, 'bitcoin/bip353'
|
|
68
62
|
|
|
69
63
|
require_relative 'bitcoin/constants'
|
|
70
64
|
require_relative 'bitcoin/ext/ecdsa'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bitcoinrb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.12.
|
|
4
|
+
version: 1.12.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- azuchi
|
|
@@ -23,20 +23,6 @@ dependencies:
|
|
|
23
23
|
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: 0.5.1
|
|
26
|
-
- !ruby/object:Gem::Dependency
|
|
27
|
-
name: eventmachine
|
|
28
|
-
requirement: !ruby/object:Gem::Requirement
|
|
29
|
-
requirements:
|
|
30
|
-
- - ">="
|
|
31
|
-
- !ruby/object:Gem::Version
|
|
32
|
-
version: '0'
|
|
33
|
-
type: :runtime
|
|
34
|
-
prerelease: false
|
|
35
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
-
requirements:
|
|
37
|
-
- - ">="
|
|
38
|
-
- !ruby/object:Gem::Version
|
|
39
|
-
version: '0'
|
|
40
26
|
- !ruby/object:Gem::Dependency
|
|
41
27
|
name: murmurhash3
|
|
42
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -65,62 +51,6 @@ dependencies:
|
|
|
65
51
|
- - ">="
|
|
66
52
|
- !ruby/object:Gem::Version
|
|
67
53
|
version: 1.5.0
|
|
68
|
-
- !ruby/object:Gem::Dependency
|
|
69
|
-
name: daemon-spawn
|
|
70
|
-
requirement: !ruby/object:Gem::Requirement
|
|
71
|
-
requirements:
|
|
72
|
-
- - ">="
|
|
73
|
-
- !ruby/object:Gem::Version
|
|
74
|
-
version: '0'
|
|
75
|
-
type: :runtime
|
|
76
|
-
prerelease: false
|
|
77
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
-
requirements:
|
|
79
|
-
- - ">="
|
|
80
|
-
- !ruby/object:Gem::Version
|
|
81
|
-
version: '0'
|
|
82
|
-
- !ruby/object:Gem::Dependency
|
|
83
|
-
name: thor
|
|
84
|
-
requirement: !ruby/object:Gem::Requirement
|
|
85
|
-
requirements:
|
|
86
|
-
- - ">="
|
|
87
|
-
- !ruby/object:Gem::Version
|
|
88
|
-
version: '0'
|
|
89
|
-
type: :runtime
|
|
90
|
-
prerelease: false
|
|
91
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
-
requirements:
|
|
93
|
-
- - ">="
|
|
94
|
-
- !ruby/object:Gem::Version
|
|
95
|
-
version: '0'
|
|
96
|
-
- !ruby/object:Gem::Dependency
|
|
97
|
-
name: eventmachine_httpserver
|
|
98
|
-
requirement: !ruby/object:Gem::Requirement
|
|
99
|
-
requirements:
|
|
100
|
-
- - ">="
|
|
101
|
-
- !ruby/object:Gem::Version
|
|
102
|
-
version: '0'
|
|
103
|
-
type: :runtime
|
|
104
|
-
prerelease: false
|
|
105
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
-
requirements:
|
|
107
|
-
- - ">="
|
|
108
|
-
- !ruby/object:Gem::Version
|
|
109
|
-
version: '0'
|
|
110
|
-
- !ruby/object:Gem::Dependency
|
|
111
|
-
name: iniparse
|
|
112
|
-
requirement: !ruby/object:Gem::Requirement
|
|
113
|
-
requirements:
|
|
114
|
-
- - ">="
|
|
115
|
-
- !ruby/object:Gem::Version
|
|
116
|
-
version: '0'
|
|
117
|
-
type: :runtime
|
|
118
|
-
prerelease: false
|
|
119
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
-
requirements:
|
|
121
|
-
- - ">="
|
|
122
|
-
- !ruby/object:Gem::Version
|
|
123
|
-
version: '0'
|
|
124
54
|
- !ruby/object:Gem::Dependency
|
|
125
55
|
name: siphash
|
|
126
56
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -177,20 +107,6 @@ dependencies:
|
|
|
177
107
|
- - "~>"
|
|
178
108
|
- !ruby/object:Gem::Version
|
|
179
109
|
version: 0.2.0
|
|
180
|
-
- !ruby/object:Gem::Dependency
|
|
181
|
-
name: observer
|
|
182
|
-
requirement: !ruby/object:Gem::Requirement
|
|
183
|
-
requirements:
|
|
184
|
-
- - "~>"
|
|
185
|
-
- !ruby/object:Gem::Version
|
|
186
|
-
version: 0.1.2
|
|
187
|
-
type: :runtime
|
|
188
|
-
prerelease: false
|
|
189
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
190
|
-
requirements:
|
|
191
|
-
- - "~>"
|
|
192
|
-
- !ruby/object:Gem::Version
|
|
193
|
-
version: 0.1.2
|
|
194
110
|
- !ruby/object:Gem::Dependency
|
|
195
111
|
name: secp256k1rb
|
|
196
112
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -233,12 +149,24 @@ dependencies:
|
|
|
233
149
|
- - '='
|
|
234
150
|
- !ruby/object:Gem::Version
|
|
235
151
|
version: 0.3.0
|
|
152
|
+
- !ruby/object:Gem::Dependency
|
|
153
|
+
name: dnsruby
|
|
154
|
+
requirement: !ruby/object:Gem::Requirement
|
|
155
|
+
requirements:
|
|
156
|
+
- - '='
|
|
157
|
+
- !ruby/object:Gem::Version
|
|
158
|
+
version: 1.73.0
|
|
159
|
+
type: :runtime
|
|
160
|
+
prerelease: false
|
|
161
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
162
|
+
requirements:
|
|
163
|
+
- - '='
|
|
164
|
+
- !ruby/object:Gem::Version
|
|
165
|
+
version: 1.73.0
|
|
236
166
|
description: The implementation of Bitcoin Protocol for Ruby.
|
|
237
167
|
email:
|
|
238
168
|
- azuchi@chaintope.com
|
|
239
|
-
executables:
|
|
240
|
-
- bitcoinrb-cli
|
|
241
|
-
- bitcoinrbd
|
|
169
|
+
executables: []
|
|
242
170
|
extensions: []
|
|
243
171
|
extra_rdoc_files: []
|
|
244
172
|
files:
|
|
@@ -257,8 +185,6 @@ files:
|
|
|
257
185
|
- bin/setup
|
|
258
186
|
- bitcoinrb.conf.sample
|
|
259
187
|
- bitcoinrb.gemspec
|
|
260
|
-
- exe/bitcoinrb-cli
|
|
261
|
-
- exe/bitcoinrbd
|
|
262
188
|
- lib/bitcoin.rb
|
|
263
189
|
- lib/bitcoin/base58.rb
|
|
264
190
|
- lib/bitcoin/bip321_uri.rb
|
|
@@ -297,6 +223,7 @@ files:
|
|
|
297
223
|
- lib/bitcoin/descriptor/sh.rb
|
|
298
224
|
- lib/bitcoin/descriptor/sorted_multi.rb
|
|
299
225
|
- lib/bitcoin/descriptor/sorted_multi_a.rb
|
|
226
|
+
- lib/bitcoin/descriptor/sp.rb
|
|
300
227
|
- lib/bitcoin/descriptor/tr.rb
|
|
301
228
|
- lib/bitcoin/descriptor/wpkh.rb
|
|
302
229
|
- lib/bitcoin/descriptor/wsh.rb
|
|
@@ -367,16 +294,6 @@ files:
|
|
|
367
294
|
- lib/bitcoin/mnemonic/wordlist/italian.txt
|
|
368
295
|
- lib/bitcoin/mnemonic/wordlist/japanese.txt
|
|
369
296
|
- lib/bitcoin/mnemonic/wordlist/spanish.txt
|
|
370
|
-
- lib/bitcoin/network.rb
|
|
371
|
-
- lib/bitcoin/network/connection.rb
|
|
372
|
-
- lib/bitcoin/network/message_handler.rb
|
|
373
|
-
- lib/bitcoin/network/peer.rb
|
|
374
|
-
- lib/bitcoin/network/peer_discovery.rb
|
|
375
|
-
- lib/bitcoin/network/pool.rb
|
|
376
|
-
- lib/bitcoin/node.rb
|
|
377
|
-
- lib/bitcoin/node/cli.rb
|
|
378
|
-
- lib/bitcoin/node/configuration.rb
|
|
379
|
-
- lib/bitcoin/node/spv.rb
|
|
380
297
|
- lib/bitcoin/opcodes.rb
|
|
381
298
|
- lib/bitcoin/out_point.rb
|
|
382
299
|
- lib/bitcoin/partial_tree.rb
|
|
@@ -390,8 +307,6 @@ files:
|
|
|
390
307
|
- lib/bitcoin/psbt/tx.rb
|
|
391
308
|
- lib/bitcoin/rpc.rb
|
|
392
309
|
- lib/bitcoin/rpc/bitcoin_core_client.rb
|
|
393
|
-
- lib/bitcoin/rpc/http_server.rb
|
|
394
|
-
- lib/bitcoin/rpc/request_handler.rb
|
|
395
310
|
- lib/bitcoin/script/multisig.rb
|
|
396
311
|
- lib/bitcoin/script/script.rb
|
|
397
312
|
- lib/bitcoin/script/script_error.rb
|
|
@@ -404,16 +319,11 @@ files:
|
|
|
404
319
|
- lib/bitcoin/secp256k1/ruby.rb
|
|
405
320
|
- lib/bitcoin/sighash_generator.rb
|
|
406
321
|
- lib/bitcoin/silent_payment.rb
|
|
322
|
+
- lib/bitcoin/silent_payment/output.rb
|
|
407
323
|
- lib/bitcoin/slip39.rb
|
|
408
324
|
- lib/bitcoin/slip39/share.rb
|
|
409
325
|
- lib/bitcoin/slip39/sss.rb
|
|
410
326
|
- lib/bitcoin/slip39/wordlist/english.txt
|
|
411
|
-
- lib/bitcoin/store.rb
|
|
412
|
-
- lib/bitcoin/store/chain_entry.rb
|
|
413
|
-
- lib/bitcoin/store/db.rb
|
|
414
|
-
- lib/bitcoin/store/db/level_db.rb
|
|
415
|
-
- lib/bitcoin/store/spv_chain.rb
|
|
416
|
-
- lib/bitcoin/store/utxo_db.rb
|
|
417
327
|
- lib/bitcoin/taproot.rb
|
|
418
328
|
- lib/bitcoin/taproot/control_block.rb
|
|
419
329
|
- lib/bitcoin/taproot/custom_depth_builder.rb
|
data/exe/bitcoinrb-cli
DELETED
data/exe/bitcoinrbd
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
require 'thor'
|
|
3
|
-
require 'bitcoin'
|
|
4
|
-
require 'daemon_spawn'
|
|
5
|
-
|
|
6
|
-
class BitcoinDaemon < DaemonSpawn::Base
|
|
7
|
-
|
|
8
|
-
def start(args)
|
|
9
|
-
puts "Bitcoinrb daemon start : #{Time.now}"
|
|
10
|
-
conf = Bitcoin::Node::Configuration.new(network: args.first[:network])
|
|
11
|
-
node = Bitcoin::Node::SPV.new(conf)
|
|
12
|
-
node.run
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def stop
|
|
16
|
-
puts "Stopping Bitcoinrb daemon : #{Time.now}"
|
|
17
|
-
node.shutdown
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
class Bitcoinrbd < Thor
|
|
23
|
-
|
|
24
|
-
class_option :network, aliases: '-n', default: :mainnet
|
|
25
|
-
|
|
26
|
-
desc 'start', 'start bitcoinrb daemon.'
|
|
27
|
-
def start
|
|
28
|
-
network = options['network'] ? options['network'].to_sym : :mainnet
|
|
29
|
-
Bitcoin.chain_params = network
|
|
30
|
-
FileUtils.mkdir_p(Bitcoin.base_dir)
|
|
31
|
-
execute_daemon(['start', network: network])
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
private
|
|
35
|
-
|
|
36
|
-
def execute_daemon(cmd_args)
|
|
37
|
-
BitcoinDaemon.spawn!({working_dir: Bitcoin.base_dir,
|
|
38
|
-
log_file: "#{Bitcoin.base_dir}/log/bitcoinrbd.log",
|
|
39
|
-
pid_file: "#{Bitcoin.base_dir}/bitcoinrbd.pid",
|
|
40
|
-
sync_log: true,
|
|
41
|
-
singleton: true}, cmd_args)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
Bitcoinrbd.start(ARGV)
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
module Bitcoin
|
|
2
|
-
|
|
3
|
-
module Network
|
|
4
|
-
|
|
5
|
-
# Basic Bitcoin P2P connection class
|
|
6
|
-
class Connection < EM::Connection
|
|
7
|
-
|
|
8
|
-
include MessageHandler
|
|
9
|
-
|
|
10
|
-
attr_reader :peer, :logger
|
|
11
|
-
|
|
12
|
-
# remote peer version.
|
|
13
|
-
attr_accessor :version
|
|
14
|
-
|
|
15
|
-
# if true, this peer send new block announcements using a headers message rather than an inv message.
|
|
16
|
-
attr_accessor :sendheaders
|
|
17
|
-
|
|
18
|
-
# minimum fee(in satoshis per kilobyte) for relay tx
|
|
19
|
-
attr_accessor :fee_rate
|
|
20
|
-
|
|
21
|
-
def initialize(peer)
|
|
22
|
-
@peer = peer
|
|
23
|
-
@logger = peer.logger
|
|
24
|
-
@sendheaders = false
|
|
25
|
-
@attr_accessor = 0
|
|
26
|
-
@message = ''
|
|
27
|
-
self.pending_connect_timeout = 5.0
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def post_init
|
|
31
|
-
logger.info "connected. #{addr}"
|
|
32
|
-
peer.conn_time = Time.now.to_i
|
|
33
|
-
begin_handshake
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# handle receiving data from remote node.
|
|
37
|
-
def receive_data(data)
|
|
38
|
-
handle(data)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def post_handshake
|
|
42
|
-
peer.post_handshake
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def addr
|
|
46
|
-
peer.addr
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# close network connection.
|
|
50
|
-
def close(msg = '')
|
|
51
|
-
logger.info "close connection with #{addr}. #{msg}"
|
|
52
|
-
close_connection_after_writing
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def handle_error(e)
|
|
56
|
-
peer.handle_error(e)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def unbind
|
|
60
|
-
logger.info "unbind. #{addr}"
|
|
61
|
-
peer.unbind
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
private
|
|
65
|
-
|
|
66
|
-
# start handshake
|
|
67
|
-
def begin_handshake
|
|
68
|
-
logger.info "begin handshake with #{addr}"
|
|
69
|
-
send_message(peer.local_version)
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
end
|