bitcoinrb 1.6.0 → 1.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f2697b9fbcca175453c80fc67d70466845c7141e6b9e9f193b5825d34bd7ffa3
4
- data.tar.gz: 61a5c26a7cfaf7abcc7c692386ff08091ea0249c9e8ea9ccb4f3231049319f47
3
+ metadata.gz: 81a899ff49ba8888d3479e7f0c93c2124098c07c68dfd293349881d724c9393b
4
+ data.tar.gz: '052092011357a7abb68ec74bbbd5939b74d75aa83d5561ce088fc80c152b3341'
5
5
  SHA512:
6
- metadata.gz: 40574931606fc1ff074f638bda7042f86c0225a5661f37622971e0b9502e039c5010d31663c34846c80f0bff2d25a02122eb4773e30a6fadad72bb170260b114
7
- data.tar.gz: aaefa2672459d1d133191aecf8cbe0e8391210647e109c6e5205e349e264ad2303b25c36d4812daf5f5f0e88fb15cc4b0bfc54653ba0a2b4a8bac9fd5fd9b5d6
6
+ metadata.gz: ce9d912ba951f85c95dd30b29f1f2d0330a168e6fdd119296186fc6e651ba92ab838c90b7d31cf1a99e17def444c6bcb9784eff6ceab0816b210428fbc77b36a
7
+ data.tar.gz: bc9f7c2e34f9f47def957b549e5c33f5a4940fb56ad2fb379f717811aedd0b5f1cc4089c0f67ff7ad1363eb9a7d7b4a4ea4405124a06b20a1674d02802720cfe
data/lib/bitcoin/block.rb CHANGED
@@ -4,11 +4,38 @@ module Bitcoin
4
4
  attr_accessor :header
5
5
  attr_accessor :transactions
6
6
 
7
+ # Constructor
8
+ # @param [Bitcoin::BlockHeader] header
9
+ # @param [Array] transactions An array of transaction.
10
+ # @raise [ArgumentError]
7
11
  def initialize(header, transactions = [])
12
+ raise ArgumentError, "header must be Bitcoin::BlockHeader." unless header.is_a?(Bitcoin::BlockHeader)
13
+ raise ArgumentError, "transactions must be an Array." unless transactions.is_a?(Array)
8
14
  @header = header
9
15
  @transactions = transactions
10
16
  end
11
17
 
18
+ # Create genesis block.
19
+ # @param [String] msg Message embedded in coinbase transaction.
20
+ # @param [Bitcoin::Script] script Coinbase transaction scriptPubkey.
21
+ # @param [Integer] time Block time.
22
+ # @param [Integer] nonce nonce.
23
+ # @param [Integer] bits nBits
24
+ # @param [Integer] version nVersion.
25
+ # @param [Integer] rewards Block rewards(satoshi).
26
+ def self.create_genesis(msg, script, time, nonce, bits, version, rewards = 50 * 100000000)
27
+ coinbase = Bitcoin::Tx.create_coinbase(msg, script, rewards)
28
+ header = BlockHeader.new(
29
+ version,
30
+ '00' * 32,
31
+ MerkleTree.build_from_leaf([coinbase.txid]).merkle_root.rhex,
32
+ time,
33
+ bits,
34
+ nonce
35
+ )
36
+ Block.new(header, [coinbase])
37
+ end
38
+
12
39
  def self.parse_from_payload(payload)
13
40
  Bitcoin::Message::Block.parse_from_payload(payload).to_block
14
41
  end
@@ -9,7 +9,7 @@ module Bitcoin
9
9
 
10
10
  def to_scripts
11
11
  candidates = [Pk.new(key), Pkh.new(key)]
12
- pubkey = extract_pubkey(key)
12
+ pubkey = extracted_key
13
13
  if pubkey.compressed?
14
14
  candidates << Wpkh.new(pubkey.pubkey)
15
15
  candidates << Sh.new(candidates.last)
@@ -18,6 +18,13 @@ module Bitcoin
18
18
  def top_level?
19
19
  false
20
20
  end
21
+
22
+ # Get extracted key.
23
+ # @return [Bitcoin::Key] Extracted key.
24
+ def extracted_key
25
+ extract_pubkey(key)
26
+ end
27
+
21
28
  end
22
29
  end
23
30
  end
@@ -18,7 +18,7 @@ module Bitcoin
18
18
  # Convert to bitcoin script.
19
19
  # @return [Bitcoin::Script]
20
20
  def to_script
21
- k = extract_pubkey(key)
21
+ k = extracted_key
22
22
  target_key = xonly ? k.xonly_pubkey : k.pubkey
23
23
  Bitcoin::Script.new << target_key << OP_CHECKSIG
24
24
  end
@@ -8,7 +8,7 @@ module Bitcoin
8
8
  end
9
9
 
10
10
  def to_script
11
- Script.to_p2pkh(extract_pubkey(key).hash160)
11
+ Script.to_p2pkh(extracted_key.hash160)
12
12
  end
13
13
  end
14
14
  end
@@ -0,0 +1,20 @@
1
+ module Bitcoin
2
+ module Descriptor
3
+ # rawtr() expression
4
+ class RawTr < KeyExpression
5
+ include Bitcoin::Opcodes
6
+
7
+ def type
8
+ :rawtr
9
+ end
10
+
11
+ def top_level?
12
+ true
13
+ end
14
+
15
+ def to_script
16
+ Bitcoin::Script.new << OP_1 << extract_pubkey(key).xonly_pubkey
17
+ end
18
+ end
19
+ end
20
+ end
@@ -12,7 +12,7 @@ module Bitcoin
12
12
  end
13
13
 
14
14
  def to_script
15
- Script.to_p2wpkh(extract_pubkey(key).hash160)
15
+ Script.to_p2wpkh(extracted_key.hash160)
16
16
  end
17
17
  end
18
18
  end
@@ -19,6 +19,7 @@ module Bitcoin
19
19
  autoload :Tr, 'bitcoin/descriptor/tr'
20
20
  autoload :MultiA, 'bitcoin/descriptor/multi_a'
21
21
  autoload :SortedMultiA, 'bitcoin/descriptor/sorted_multi_a'
22
+ autoload :RawTr, 'bitcoin/descriptor/raw_tr'
22
23
  autoload :Checksum, 'bitcoin/descriptor/checksum'
23
24
 
24
25
  module_function
@@ -104,6 +105,13 @@ module Bitcoin
104
105
  Tr.new(key, tree)
105
106
  end
106
107
 
108
+ # Generate taproot output script descriptor.
109
+ # @param [String] key
110
+ # @return [Bitcoin::Descriptor::RawTr]
111
+ def rawtr(key)
112
+ RawTr.new(key)
113
+ end
114
+
107
115
  # Generate tapscript multisig output for given keys.
108
116
  # @param [Integer] threshold the threshold of multisig.
109
117
  # @param [Array[String]] keys an array of keys.
@@ -169,6 +177,8 @@ module Bitcoin
169
177
  else
170
178
  tr(key, parse(rest, false))
171
179
  end
180
+ when 'rawtr'
181
+ rawtr(args_str)
172
182
  else
173
183
  raise ArgumentError, "Parse failed: #{string}"
174
184
  end
@@ -71,7 +71,8 @@ module Bitcoin
71
71
  tx.in[0].script_witness = Bitcoin::ScriptWitness.parse_from_payload(sig)
72
72
  script_pubkey = Bitcoin::Script.parse_from_addr(address)
73
73
  tx_out = Bitcoin::TxOut.new(script_pubkey: script_pubkey)
74
- interpreter = Bitcoin::ScriptInterpreter.new(checker: Bitcoin::TxChecker.new(tx: tx, input_index: 0, prevouts: [tx_out]))
74
+ flags = Bitcoin::STANDARD_SCRIPT_VERIFY_FLAGS
75
+ interpreter = Bitcoin::ScriptInterpreter.new(flags: flags, checker: Bitcoin::TxChecker.new(tx: tx, input_index: 0, prevouts: [tx_out]))
75
76
  interpreter.verify_script(Bitcoin::Script.new, script_pubkey, tx.in[0].script_witness)
76
77
  else
77
78
  raise ArgumentError, "This address unsupported."
@@ -11,6 +11,7 @@ module Bitcoin
11
11
 
12
12
  def self.parse_from_payload(payload)
13
13
  buf = payload.is_a?(StringIO) ? payload : StringIO.new(payload)
14
+ return self.new if buf.eof?
14
15
  size = Bitcoin.unpack_var_int_from_io(buf)
15
16
  stack = size.times.map do
16
17
  buf.read(Bitcoin.unpack_var_int_from_io(buf))
@@ -0,0 +1,5 @@
1
+ module Bitcoin
2
+ module SilentPayment
3
+ autoload :Addr, 'bitcoin/sp/addr'
4
+ end
5
+ end
@@ -0,0 +1,55 @@
1
+ module Bitcoin
2
+ module SilentPayment
3
+ class Addr
4
+
5
+ HRP_MAINNET = 'sp'
6
+ HRP_TESTNET = 'tsp'
7
+ MAX_CHARACTERS = 1023
8
+
9
+ attr_reader :version
10
+ attr_reader :scan_key
11
+ attr_reader :spend_key
12
+
13
+ # Constructor.
14
+ # @param [Bitcoin::Key] scan_key
15
+ # @param [Bitcoin::Key] spend_key
16
+ def initialize(version, scan_key:, spend_key:)
17
+ raise ArgumentError, "version must be integer." unless version.is_a?(Integer)
18
+ raise ArgumentError, "scan_key must be Bitcoin::Key." unless scan_key.is_a?(Bitcoin::Key)
19
+ raise ArgumentError, "spend_key must be Bitcoin::Key." unless spend_key.is_a?(Bitcoin::Key)
20
+ raise ArgumentError, "version '#{version}' is unsupported." unless version.zero?
21
+
22
+ @version = version
23
+ @scan_key = scan_key
24
+ @spend_key = spend_key
25
+ end
26
+
27
+ # Parse silent payment address.
28
+ # @param [String] A silent payment address.
29
+ # @return [Bitcoin::SilentPayment::Addr]
30
+ def self.from_string(addr)
31
+ raise ArgumentError, "addr must be string." unless addr.is_a?(String)
32
+ hrp, data, spec = Bech32.decode(addr, MAX_CHARACTERS)
33
+ unless hrp == Bitcoin.chain_params.mainnet? ? HRP_MAINNET : HRP_TESTNET
34
+ raise ArgumentError, "The specified hrp is different from the current network HRP."
35
+ end
36
+ raise ArgumentError, "spec must be bech32m." unless spec == Bech32::Encoding::BECH32M
37
+
38
+ ver = data[0]
39
+ payload = Bech32.convert_bits(data[1..-1], 5, 8, false).pack("C*")
40
+ scan_key = Bitcoin::Key.new(pubkey: payload[0...33].bth, key_type: Bitcoin::Key::TYPES[:compressed])
41
+ spend_key = Bitcoin::Key.new(pubkey: payload[33..-1].bth, key_type: Bitcoin::Key::TYPES[:compressed])
42
+ Addr.new(ver, scan_key: scan_key, spend_key: spend_key)
43
+ end
44
+
45
+ # Get silent payment address.
46
+ # @return [String]
47
+ def to_s
48
+ hrp = Bitcoin.chain_params.mainnet? ? HRP_MAINNET : HRP_TESTNET
49
+ payload = [scan_key.pubkey + spend_key.pubkey].pack("H*").unpack('C*')
50
+ Bech32.encode(hrp, [version] + Bech32.convert_bits(payload, 8, 5), Bech32::Encoding::BECH32M)
51
+ end
52
+
53
+ end
54
+ end
55
+ end
data/lib/bitcoin/tx.rb CHANGED
@@ -33,6 +33,19 @@ module Bitcoin
33
33
  alias_method :in, :inputs
34
34
  alias_method :out, :outputs
35
35
 
36
+ # Create coinbase transaction.
37
+ # @param [String] msg Message embedded in coinbase transaction.
38
+ # @param [Bitcoin::Script] script Coinbase transaction scriptPubkey.
39
+ # @param [Integer] rewards Coinbase Transaction Rewards
40
+ # @return [Bitcoin::Tx] Coinbase transaction.
41
+ def self.create_coinbase(msg, script, rewards = 50 * 100000000)
42
+ coinbase = Tx.new
43
+ script_sig = Bitcoin::Script.new << 486604799 << "04" << msg.bth
44
+ coinbase.in << TxIn.new(out_point: OutPoint.create_coinbase_outpoint, script_sig: script_sig)
45
+ coinbase.out << TxOut.new(value: rewards, script_pubkey: script)
46
+ coinbase
47
+ end
48
+
36
49
  def self.parse_from_payload(payload, non_witness: false, strict: false)
37
50
  buf = payload.is_a?(String) ? StringIO.new(payload) : payload
38
51
  tx = new
@@ -1,3 +1,3 @@
1
1
  module Bitcoin
2
- VERSION = "1.6.0"
2
+ VERSION = "1.7.0"
3
3
  end
data/lib/bitcoin.rb CHANGED
@@ -61,6 +61,7 @@ module Bitcoin
61
61
  autoload :SigHashGenerator, 'bitcoin/sighash_generator'
62
62
  autoload :MessageSign, 'bitcoin/message_sign'
63
63
  autoload :Taproot, 'bitcoin/taproot'
64
+ autoload :SilentPayment, 'bitcoin/silent_payment'
64
65
  autoload :BIP324, 'bitcoin/bip324'
65
66
 
66
67
  require_relative 'bitcoin/constants'
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: 1.6.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - azuchi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-07-09 00:00:00.000000000 Z
11
+ date: 2024-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ecdsa_ext
@@ -360,6 +360,7 @@ files:
360
360
  - lib/bitcoin/descriptor/pk.rb
361
361
  - lib/bitcoin/descriptor/pkh.rb
362
362
  - lib/bitcoin/descriptor/raw.rb
363
+ - lib/bitcoin/descriptor/raw_tr.rb
363
364
  - lib/bitcoin/descriptor/script_expression.rb
364
365
  - lib/bitcoin/descriptor/sh.rb
365
366
  - lib/bitcoin/descriptor/sorted_multi.rb
@@ -469,10 +470,12 @@ files:
469
470
  - lib/bitcoin/secp256k1/rfc6979.rb
470
471
  - lib/bitcoin/secp256k1/ruby.rb
471
472
  - lib/bitcoin/sighash_generator.rb
473
+ - lib/bitcoin/silent_payment.rb
472
474
  - lib/bitcoin/slip39.rb
473
475
  - lib/bitcoin/slip39/share.rb
474
476
  - lib/bitcoin/slip39/sss.rb
475
477
  - lib/bitcoin/slip39/wordlist/english.txt
478
+ - lib/bitcoin/sp/addr.rb
476
479
  - lib/bitcoin/store.rb
477
480
  - lib/bitcoin/store/chain_entry.rb
478
481
  - lib/bitcoin/store/db.rb