bitcoinrb 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
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