bitcoinrb 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +1 -1
- data/.ruby-version +1 -1
- data/README.md +2 -0
- data/bitcoinrb.gemspec +3 -3
- data/lib/bitcoin/constants.rb +2 -3
- data/lib/bitcoin/ext_key.rb +6 -4
- data/lib/bitcoin/key.rb +1 -0
- data/lib/bitcoin/message_sign.rb +90 -15
- data/lib/bitcoin/node/cli.rb +6 -0
- data/lib/bitcoin/payment_code.rb +1 -1
- data/lib/bitcoin/psbt/input.rb +26 -0
- data/lib/bitcoin/psbt/output.rb +12 -1
- data/lib/bitcoin/psbt/proprietary.rb +4 -0
- data/lib/bitcoin/psbt/tx.rb +12 -0
- data/lib/bitcoin/script/script.rb +2 -5
- data/lib/bitcoin/secp256k1/ruby.rb +8 -5
- data/lib/bitcoin/taproot.rb +3 -1
- data/lib/bitcoin/version.rb +1 -1
- metadata +14 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 23f677d00426b94e0bdcee887901bb1e89a98c65ae61b0a025c7d95467dcb484
|
4
|
+
data.tar.gz: 7426638ec33999d466026a09a91517fe698adc0a55f32db6d416dc3f4ad6a386
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 960aada8b3db4c610a2b206254f878af9c149f81ce42a53a2ebe8441e0a5179964a9a505807ae2b7519349c4a48125397acb20b412cfb84ea59d58957acd84e4
|
7
|
+
data.tar.gz: 493c6e06d7fb686dda65fd4bc4075e3716004427beab0cce9e040060711ad4a7197d0fdece2838d130ed6b1b64cdc94a37957a8354d7629bf9bd68fc02d326e4
|
data/.github/workflows/ruby.yml
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-3.
|
1
|
+
ruby-3.2.0
|
data/README.md
CHANGED
@@ -67,6 +67,8 @@ And then add to your .rb file:
|
|
67
67
|
|
68
68
|
## Usage
|
69
69
|
|
70
|
+
Examples can be found on the [wiki](https://github.com/chaintope/bitcoinrb/wiki).
|
71
|
+
|
70
72
|
### Chain selection
|
71
73
|
|
72
74
|
The parameters of the blockchain are managed by `Bitcoin::ChainParams`. Switch chain parameters as follows:
|
data/bitcoinrb.gemspec
CHANGED
@@ -20,10 +20,10 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
21
|
spec.require_paths = ["lib"]
|
22
22
|
|
23
|
-
spec.add_runtime_dependency '
|
23
|
+
spec.add_runtime_dependency 'ecdsa_ext', '~> 0.5.0'
|
24
24
|
spec.add_runtime_dependency 'eventmachine'
|
25
25
|
spec.add_runtime_dependency 'murmurhash3'
|
26
|
-
spec.add_runtime_dependency 'bech32', '
|
26
|
+
spec.add_runtime_dependency 'bech32', '>= 1.3.0'
|
27
27
|
spec.add_runtime_dependency 'daemon-spawn'
|
28
28
|
spec.add_runtime_dependency 'thor'
|
29
29
|
spec.add_runtime_dependency 'ffi'
|
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.add_runtime_dependency 'siphash'
|
34
34
|
spec.add_runtime_dependency 'protobuf', '3.8.5'
|
35
35
|
spec.add_runtime_dependency 'json_pure', '>= 2.3.1'
|
36
|
-
spec.add_runtime_dependency 'bip-schnorr', '>= 0.
|
36
|
+
spec.add_runtime_dependency 'bip-schnorr', '>= 0.5.0'
|
37
37
|
spec.add_runtime_dependency 'base32', '>= 0.3.4'
|
38
38
|
|
39
39
|
# for options
|
data/lib/bitcoin/constants.rb
CHANGED
@@ -57,9 +57,8 @@ module Bitcoin
|
|
57
57
|
SCRIPT_VERIFY_CONST_SCRIPTCODE = (1 << 16) # Making OP_CODESEPARATOR and FindAndDelete fail any non-segwit scripts
|
58
58
|
SCRIPT_VERIFY_TAPROOT = (1 << 17) # Taproot/Tapscript validation (BIPs 341 & 342)
|
59
59
|
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION = (1 << 18) # Making unknown Taproot leaf versions non-standard
|
60
|
-
|
61
|
-
|
62
|
-
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE = (1 << 21) # Making unknown public key versions (in BIP 342 scripts) non-standard
|
60
|
+
SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS = (1 << 19) # Making unknown OP_SUCCESS non-standard
|
61
|
+
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE = (1 << 20) # Making unknown public key versions (in BIP 342 scripts) non-standard
|
63
62
|
|
64
63
|
MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH
|
65
64
|
|
data/lib/bitcoin/ext_key.rb
CHANGED
@@ -27,7 +27,8 @@ module Bitcoin
|
|
27
27
|
l = Bitcoin.hmac_sha512('Bitcoin seed', seed.htb)
|
28
28
|
left = l[0..31].bth.to_i(16)
|
29
29
|
raise 'invalid key' if left >= CURVE_ORDER || left == 0
|
30
|
-
|
30
|
+
l_priv = ECDSA::Format::IntegerOctetString.encode(left, 32)
|
31
|
+
ext_key.key = Bitcoin::Key.new(priv_key: l_priv.bth, key_type: Bitcoin::Key::TYPES[:compressed])
|
31
32
|
ext_key.chain_code = l[32..-1]
|
32
33
|
ext_key
|
33
34
|
end
|
@@ -110,8 +111,8 @@ module Bitcoin
|
|
110
111
|
raise 'invalid key' if left >= CURVE_ORDER
|
111
112
|
child_priv = (left + key.priv_key.to_i(16)) % CURVE_ORDER
|
112
113
|
raise 'invalid key ' if child_priv >= CURVE_ORDER
|
113
|
-
|
114
|
-
|
114
|
+
child_priv = ECDSA::Format::IntegerOctetString.encode(child_priv, 32)
|
115
|
+
new_key.key = Bitcoin::Key.new(priv_key: child_priv.bth, key_type: key_type)
|
115
116
|
new_key.chain_code = l[32..-1]
|
116
117
|
new_key.ver = version
|
117
118
|
new_key
|
@@ -280,7 +281,8 @@ module Bitcoin
|
|
280
281
|
l = Bitcoin.hmac_sha512(chain_code, data)
|
281
282
|
left = l[0..31].bth.to_i(16)
|
282
283
|
raise 'invalid key' if left >= CURVE_ORDER
|
283
|
-
|
284
|
+
l_priv = ECDSA::Format::IntegerOctetString.encode(left, 32)
|
285
|
+
p1 = Bitcoin::Key.new(priv_key: l_priv.bth, key_type: Bitcoin::Key::TYPES[:uncompressed]).to_point
|
284
286
|
p2 = Bitcoin::Key.new(pubkey: pubkey, key_type: key_type).to_point
|
285
287
|
new_key.pubkey = (p1 + p2).to_hex
|
286
288
|
new_key.chain_code = l[32..-1]
|
data/lib/bitcoin/key.rb
CHANGED
@@ -39,6 +39,7 @@ module Bitcoin
|
|
39
39
|
@secp256k1_module = Bitcoin.secp_impl
|
40
40
|
@priv_key = priv_key
|
41
41
|
if @priv_key
|
42
|
+
raise ArgumentError, 'Private key must be 32 bytes.' unless priv_key.htb.bytesize == 32
|
42
43
|
raise ArgumentError, Errors::Messages::INVALID_PRIV_KEY unless validate_private_key_range(@priv_key)
|
43
44
|
end
|
44
45
|
if pubkey
|
data/lib/bitcoin/message_sign.rb
CHANGED
@@ -6,14 +6,42 @@ module Bitcoin
|
|
6
6
|
|
7
7
|
module_function
|
8
8
|
|
9
|
+
FORMAT_LEGACY = :legacy
|
10
|
+
FORMAT_SIMPLE = :simple
|
11
|
+
FORMAT_FULL = :full
|
12
|
+
|
9
13
|
# Sign a message.
|
10
|
-
# @param [Bitcoin::Key] key Private key to sign
|
11
|
-
# @param [String] message The message to
|
14
|
+
# @param [Bitcoin::Key] key Private key to sign.
|
15
|
+
# @param [String] message The message to be signed.
|
16
|
+
# @param [String] address An address of the key used for signing (required for full or simple format).
|
17
|
+
# @param [String] format Format of signature data. Default is +FORMAT_LEGACY+.
|
18
|
+
# @param [String] prefix (Optional) Prefix used in legacy format.
|
12
19
|
# @return [String] Signature, base64 encoded.
|
13
|
-
def sign_message(key, message, prefix: Bitcoin.chain_params.message_magic)
|
14
|
-
|
15
|
-
|
16
|
-
|
20
|
+
def sign_message(key, message, prefix: Bitcoin.chain_params.message_magic, format: FORMAT_LEGACY, address: nil)
|
21
|
+
validate_format!(format)
|
22
|
+
digest = message_hash(message, prefix: prefix, legacy: format == FORMAT_LEGACY)
|
23
|
+
sig = case format
|
24
|
+
when FORMAT_LEGACY
|
25
|
+
key.sign_compact(digest)
|
26
|
+
else
|
27
|
+
validate_address!(address)
|
28
|
+
addr = Bitcoin::Script.parse_from_addr(address)
|
29
|
+
sig_ver, algo = if addr.p2wpkh?
|
30
|
+
[:witness_v0, :ecdsa]
|
31
|
+
elsif addr.p2tr?
|
32
|
+
[:taproot, :schnorr]
|
33
|
+
else
|
34
|
+
raise ArgumentError "#{address} dose not supported."
|
35
|
+
end
|
36
|
+
tx = to_sign_tx(digest, address)
|
37
|
+
prev_out = Bitcoin::TxOut.new(script_pubkey: addr)
|
38
|
+
sighash = tx.sighash_for_input(0, addr, sig_version: sig_ver, amount: 0, prevouts: [prev_out])
|
39
|
+
sig = key.sign(sighash, algo: algo) + [Bitcoin::SIGHASH_TYPE[:all]].pack('C')
|
40
|
+
tx.in[0].script_witness.stack << sig
|
41
|
+
tx.in[0].script_witness.stack << key.pubkey.htb
|
42
|
+
format == FORMAT_SIMPLE ? tx.in[0].script_witness.to_payload : tx.to_payload
|
43
|
+
end
|
44
|
+
Base64.strict_encode64(sig)
|
17
45
|
end
|
18
46
|
|
19
47
|
# Verify a signed message.
|
@@ -23,25 +51,72 @@ module Bitcoin
|
|
23
51
|
# @return [Boolean] Verification result.
|
24
52
|
def verify_message(address, signature, message, prefix: Bitcoin.chain_params.message_magic)
|
25
53
|
validate_address!(address)
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
54
|
+
begin
|
55
|
+
sig = Base64.strict_decode64(signature)
|
56
|
+
rescue ArgumentError
|
57
|
+
raise ArgumentError, 'Invalid signature'
|
58
|
+
end
|
59
|
+
begin
|
60
|
+
# Legacy verification
|
61
|
+
pubkey = Bitcoin::Key.recover_compact(message_hash(message, prefix: prefix, legacy: true), sig)
|
62
|
+
return false unless pubkey
|
63
|
+
pubkey.to_p2pkh == address
|
64
|
+
rescue ArgumentError
|
65
|
+
# BIP322 verification
|
66
|
+
tx = to_sign_tx(message_hash(message, prefix: prefix, legacy: false), address)
|
67
|
+
tx.in[0].script_witness = Bitcoin::ScriptWitness.parse_from_payload(sig)
|
68
|
+
script_pubkey = Bitcoin::Script.parse_from_addr(address)
|
69
|
+
tx_out = Bitcoin::TxOut.new(script_pubkey: script_pubkey)
|
70
|
+
interpreter = Bitcoin::ScriptInterpreter.new(checker: Bitcoin::TxChecker.new(tx: tx, input_index: 0, prevouts: [tx_out]))
|
71
|
+
interpreter.verify_script(Bitcoin::Script.new, script_pubkey, tx.in[0].script_witness)
|
72
|
+
end
|
32
73
|
end
|
33
74
|
|
34
75
|
# Hashes a message for signing and verification.
|
35
|
-
def message_hash(message, prefix: Bitcoin.chain_params.message_magic)
|
36
|
-
|
76
|
+
def message_hash(message, prefix: Bitcoin.chain_params.message_magic, legacy: true)
|
77
|
+
if legacy
|
78
|
+
Bitcoin.double_sha256(Bitcoin.pack_var_string(prefix) << Bitcoin.pack_var_string(message))
|
79
|
+
else
|
80
|
+
Bitcoin.tagged_hash('BIP0322-signed-message', message)
|
81
|
+
end
|
37
82
|
end
|
38
83
|
|
39
84
|
def validate_address!(address)
|
40
85
|
raise ArgumentError, 'Invalid address' unless Bitcoin.valid_address?(address)
|
41
86
|
script = Bitcoin::Script.parse_from_addr(address)
|
42
|
-
raise ArgumentError, '
|
87
|
+
raise ArgumentError, 'This address unsupported' if script.p2sh? || script.p2wsh?
|
88
|
+
end
|
89
|
+
|
90
|
+
def validate_format!(format)
|
91
|
+
unless [FORMAT_LEGACY, FORMAT_FULL, FORMAT_SIMPLE].include?(format)
|
92
|
+
raise ArgumentError "Invalid format specified."
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_spend_tx(digest, addr)
|
97
|
+
validate_address!(addr)
|
98
|
+
message_challenge = Bitcoin::Script.parse_from_addr(addr)
|
99
|
+
tx = Bitcoin::Tx.new
|
100
|
+
tx.version = 0
|
101
|
+
tx.lock_time = 0
|
102
|
+
prev_out = Bitcoin::OutPoint.create_coinbase_outpoint
|
103
|
+
script_sig = Bitcoin::Script.new << Bitcoin::Opcodes::OP_0 << digest
|
104
|
+
tx.in << Bitcoin::TxIn.new(out_point: prev_out, sequence: 0, script_sig: script_sig)
|
105
|
+
tx.out << Bitcoin::TxOut.new(script_pubkey: message_challenge)
|
106
|
+
tx
|
107
|
+
end
|
108
|
+
|
109
|
+
def to_sign_tx(digest, addr)
|
110
|
+
tx = Bitcoin::Tx.new
|
111
|
+
tx.version = 0
|
112
|
+
tx.lock_time = 0
|
113
|
+
prev_out = Bitcoin::OutPoint.from_txid(to_spend_tx(digest, addr).txid, 0)
|
114
|
+
tx.in << Bitcoin::TxIn.new(out_point: prev_out, sequence: 0)
|
115
|
+
tx.out << Bitcoin::TxOut.new(script_pubkey: Bitcoin::Script.new << Bitcoin::Opcodes::OP_RETURN)
|
116
|
+
tx
|
43
117
|
end
|
44
118
|
|
45
119
|
private_class_method :validate_address!
|
120
|
+
private_class_method :validate_format!
|
46
121
|
end
|
47
122
|
end
|
data/lib/bitcoin/node/cli.rb
CHANGED
@@ -9,6 +9,12 @@ module Bitcoin
|
|
9
9
|
|
10
10
|
class_option :network, aliases: '-n', default: :mainnet
|
11
11
|
|
12
|
+
desc 'decodepsbt <base64 psbt string>', "Return a JSON object representing the serialized, base64-encoded partially signed Bitcoin transaction."
|
13
|
+
def decodepsbt(base64)
|
14
|
+
psbt = Bitcoin::PSBT::Tx.parse_from_base64(base64)
|
15
|
+
puts JSON.pretty_generate(psbt.to_h)
|
16
|
+
end
|
17
|
+
|
12
18
|
desc 'getblockchaininfo', 'Returns an object containing various state info regarding blockchain processing.'
|
13
19
|
def getblockchaininfo
|
14
20
|
request('getblockchaininfo')
|
data/lib/bitcoin/payment_code.rb
CHANGED
@@ -61,7 +61,7 @@ module Bitcoin
|
|
61
61
|
raise ArgumentError, 'invalid version byte' unless hex[0..1] == VERSION_BYTE
|
62
62
|
raise ArgumentError, 'invalid version' unless PaymentCode.support_version?(version)
|
63
63
|
raise ArgumentError, 'invalid sign' unless PaymentCode.support_sign?(sign)
|
64
|
-
raise ArgumentError, Errors::Messages::INVALID_PUBLIC_KEY unless Bitcoin::Key.new(
|
64
|
+
raise ArgumentError, Errors::Messages::INVALID_PUBLIC_KEY unless Bitcoin::Key.new(pubkey: sign + public_key).fully_valid_pubkey?
|
65
65
|
raise ArgumentError, Errors::Messages::INVALID_CHECKSUM unless Bitcoin.calc_checksum(payment_code) == hex[-8..-1]
|
66
66
|
|
67
67
|
x_value = payment_code[8..71]
|
data/lib/bitcoin/psbt/input.rb
CHANGED
@@ -283,6 +283,32 @@ module Bitcoin
|
|
283
283
|
self
|
284
284
|
end
|
285
285
|
|
286
|
+
def to_h
|
287
|
+
h = {}
|
288
|
+
h[:non_witness_utxo] = non_witness_utxo.to_h if non_witness_utxo
|
289
|
+
h[:witness_utxo] = witness_utxo.to_h if witness_utxo
|
290
|
+
h[:redeem_script] = redeem_script.to_h if redeem_script
|
291
|
+
h[:witness_script] = witness_script.to_h if redeem_script
|
292
|
+
h[:final_script_sig] = final_script_sig.to_h if final_script_sig
|
293
|
+
h[:final_script_witness] = final_script_witness.to_h if final_script_witness
|
294
|
+
h[:bip32_derivs] = hd_key_paths.values.map(&:to_h) unless hd_key_paths.empty?
|
295
|
+
h[:partial_signatures] = partial_sigs.map {|k, v| {"#{k}": v.bth}} unless partial_sigs.empty?
|
296
|
+
h[:sighash_type] = sighash_type if sighash_type
|
297
|
+
h[:ripemd160_preimages] = ripemd160_preimages.map {|k, v| {"#{k}": v}} unless ripemd160_preimages.empty?
|
298
|
+
h[:sha256_preimages] = sha256_preimages.map {|k, v| {"#{k}": v}} unless sha256_preimages.empty?
|
299
|
+
h[:hash160_preimages] = hash160_preimages.map {|k, v| {"#{k}": v}} unless hash160_preimages.empty?
|
300
|
+
h[:hash256_preimages] = hash256_preimages.map {|k, v| {"#{k}": v}} unless hash256_preimages.empty?
|
301
|
+
h[:proprietary] = proprietaries.map(&:to_h) unless proprietaries.empty?
|
302
|
+
h[:tap_key_sig] = tap_key_sig if tap_key_sig
|
303
|
+
h[:tap_script_sig] = tap_script_sigs.map {|k, v| {"#{k}": v}} unless tap_script_sigs.empty?
|
304
|
+
h[:tap_leaf_script] = tap_leaf_scripts.map {|k, v| {"#{k}": v}} unless tap_leaf_scripts.empty?
|
305
|
+
h[:tap_bip32_derivs] = tap_bip32_derivations.map{|k, v| {"#{k}": v}} unless tap_bip32_derivations.empty?
|
306
|
+
h[:tap_internal_key] = tap_internal_key if tap_internal_key
|
307
|
+
h[:tap_merkle_root] = tap_merkle_root if tap_merkle_root
|
308
|
+
h[:unknown] = unknowns.map {|k, v| {"#{k}": v.bth}} unless unknowns.empty?
|
309
|
+
h
|
310
|
+
end
|
311
|
+
|
286
312
|
end
|
287
313
|
|
288
314
|
end
|
data/lib/bitcoin/psbt/output.rb
CHANGED
@@ -100,7 +100,18 @@ module Bitcoin
|
|
100
100
|
combined
|
101
101
|
end
|
102
102
|
|
103
|
+
def to_h
|
104
|
+
h = {}
|
105
|
+
h[:redeem_script] = redeem_script.bth if redeem_script
|
106
|
+
h[:witness_script] = witness_script.bth if witness_script
|
107
|
+
h[:bip32_derivs] = hd_key_paths.values.map(&:to_h) unless hd_key_paths.empty?
|
108
|
+
h[:proprietary] = proprietaries.map(&:to_h) unless proprietaries.empty?
|
109
|
+
h[:tap_internal_key] = tap_internal_key if tap_internal_key
|
110
|
+
h[:tap_tree] = tap_tree if tap_tree
|
111
|
+
h[:tap_bip32_derivs] = tap_bip32_derivations.map{|k, v| {"#{k}": v}} unless tap_bip32_derivations.empty?
|
112
|
+
h[:unknown] = unknowns.map {|k, v| {"#{k}": v.bth}} unless unknowns.empty?
|
113
|
+
h
|
114
|
+
end
|
103
115
|
end
|
104
|
-
|
105
116
|
end
|
106
117
|
end
|
data/lib/bitcoin/psbt/tx.rb
CHANGED
@@ -177,6 +177,18 @@ module Bitcoin
|
|
177
177
|
end
|
178
178
|
end
|
179
179
|
|
180
|
+
def to_h
|
181
|
+
{
|
182
|
+
tx: tx.to_h,
|
183
|
+
global_xpubs: xpubs.map(&:to_h),
|
184
|
+
psbt_version: version,
|
185
|
+
proprietary: proprietaries.map(&:to_h),
|
186
|
+
unknown: unknowns.map {|k, v| {"#{k}": v}},
|
187
|
+
inputs: inputs.map(&:to_h),
|
188
|
+
outputs: outputs.map(&:to_h)
|
189
|
+
}
|
190
|
+
end
|
191
|
+
|
180
192
|
# update input key-value maps.
|
181
193
|
# @param [Bitcoin::Tx] prev_tx previous tx reference by input.
|
182
194
|
# @param [Bitcoin::Script] redeem_script redeem script to set input.
|
@@ -543,11 +543,8 @@ module Bitcoin
|
|
543
543
|
|
544
544
|
def to_h
|
545
545
|
h = {asm: to_s, hex: to_hex, type: type}
|
546
|
-
|
547
|
-
|
548
|
-
h[:req_sigs] = multisig? ? Bitcoin::Opcodes.opcode_to_small_int(chunks[0].bth.to_i(16)) :addrs.size
|
549
|
-
h[:addresses] = addrs
|
550
|
-
end
|
546
|
+
addr = to_addr
|
547
|
+
h[:address] = addr if addr
|
551
548
|
h
|
552
549
|
end
|
553
550
|
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'ecdsa_ext'
|
2
|
+
require 'ecdsa/ext/sign_verify'
|
3
|
+
|
1
4
|
module Bitcoin
|
2
5
|
module Secp256k1
|
3
6
|
|
@@ -10,9 +13,9 @@ module Bitcoin
|
|
10
13
|
# generate ec private key and public key
|
11
14
|
def generate_key_pair(compressed: true)
|
12
15
|
private_key = 1 + SecureRandom.random_number(GROUP.order - 1)
|
13
|
-
public_key = GROUP.generator.
|
16
|
+
public_key = GROUP.generator.to_jacobian * private_key
|
14
17
|
privkey = ECDSA::Format::IntegerOctetString.encode(private_key, 32)
|
15
|
-
pubkey = public_key.to_hex(compressed)
|
18
|
+
pubkey = public_key.to_affine.to_hex(compressed)
|
16
19
|
[privkey.bth, pubkey]
|
17
20
|
end
|
18
21
|
|
@@ -23,8 +26,8 @@ module Bitcoin
|
|
23
26
|
end
|
24
27
|
|
25
28
|
def generate_pubkey(privkey, compressed: true)
|
26
|
-
public_key =
|
27
|
-
public_key.to_hex(compressed)
|
29
|
+
public_key = GROUP.generator.to_jacobian * privkey.to_i(16)
|
30
|
+
public_key.to_affine.to_hex(compressed)
|
28
31
|
end
|
29
32
|
|
30
33
|
# Check whether valid x-only public key or not.
|
@@ -132,7 +135,7 @@ module Bitcoin
|
|
132
135
|
nonce = RFC6979.generate_rfc6979_nonce(privkey + data, extra_entropy)
|
133
136
|
|
134
137
|
# port form ecdsa gem.
|
135
|
-
r_point = GROUP.
|
138
|
+
r_point = (GROUP.generator.to_jacobian * nonce).to_affine
|
136
139
|
|
137
140
|
point_field = ECDSA::PrimeField.new(GROUP.order)
|
138
141
|
r = point_field.mod(r_point.x)
|
data/lib/bitcoin/taproot.rb
CHANGED
@@ -40,7 +40,9 @@ module Bitcoin
|
|
40
40
|
private_key = p.has_even_y? ? internal_private_key.priv_key.to_i(16) :
|
41
41
|
ECDSA::Group::Secp256k1.order - internal_private_key.priv_key.to_i(16)
|
42
42
|
t = tweak(internal_private_key, merkle_root)
|
43
|
-
|
43
|
+
private_key = ECDSA::Format::IntegerOctetString.encode(
|
44
|
+
(t.bti + private_key) % ECDSA::Group::Secp256k1.order, 32)
|
45
|
+
Bitcoin::Key.new(priv_key: private_key.bth)
|
44
46
|
end
|
45
47
|
end
|
46
48
|
end
|
data/lib/bitcoin/version.rb
CHANGED
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bitcoinrb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
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: 2023-04-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: ecdsa_ext
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 0.5.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 0.5.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: eventmachine
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,16 +56,16 @@ dependencies:
|
|
56
56
|
name: bech32
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 1.
|
61
|
+
version: 1.3.0
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 1.
|
68
|
+
version: 1.3.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: daemon-spawn
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -198,14 +198,14 @@ dependencies:
|
|
198
198
|
requirements:
|
199
199
|
- - ">="
|
200
200
|
- !ruby/object:Gem::Version
|
201
|
-
version: 0.
|
201
|
+
version: 0.5.0
|
202
202
|
type: :runtime
|
203
203
|
prerelease: false
|
204
204
|
version_requirements: !ruby/object:Gem::Requirement
|
205
205
|
requirements:
|
206
206
|
- - ">="
|
207
207
|
- !ruby/object:Gem::Version
|
208
|
-
version: 0.
|
208
|
+
version: 0.5.0
|
209
209
|
- !ruby/object:Gem::Dependency
|
210
210
|
name: base32
|
211
211
|
requirement: !ruby/object:Gem::Requirement
|
@@ -517,7 +517,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
517
517
|
- !ruby/object:Gem::Version
|
518
518
|
version: '0'
|
519
519
|
requirements: []
|
520
|
-
rubygems_version: 3.
|
520
|
+
rubygems_version: 3.4.1
|
521
521
|
signing_key:
|
522
522
|
specification_version: 4
|
523
523
|
summary: The implementation of Bitcoin Protocol for Ruby.
|