bitcoinrb 1.2.0 → 1.3.0
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/.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.
|