bitcoinrb 0.2.1 → 0.2.2

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: 79b3878cc9efefd8c38b5cd870144bc23a80bbf7bf1c741378dd66c9e5ebdbf8
4
- data.tar.gz: a5d9956a5a6b7bed15b73e552b84110d9636f1b069c1d97978be4e94c1e0a0f0
3
+ metadata.gz: 524753cfa61041f101f72d76e914f70b20b504fb0eecad9d378a436afe7db718
4
+ data.tar.gz: f3181a60120da9f892ceaaaaf22aba5923b26f495fb9fb9dd314c5cce8127129
5
5
  SHA512:
6
- metadata.gz: b779fd9decef5b224144dae60e06b99f3ac0fbb17b34202af0ce31eb2bd7e0a6076b3a940dcfe2e460923017c14feb40c2d0bf891f3ebe9553b65be124559a32
7
- data.tar.gz: 7f011d31ab1ec5364cc8f04a63b6baf74d37db05d49666588dd1329d5005f3ba01a8e8b83752989121b73c3956eda8a5808365b729f6d21dc136f6abf0c817cd
6
+ metadata.gz: da27669ddabc4d64bf3c96d4e83eb8c5d90ef837ed91b6f2e1d0e7d50c74153c62ff39eecb1867463f5a8435f7643d62ba6108e7a10d1fa46e4b10178fe8e2f1
7
+ data.tar.gz: 2f85e04fecddba5bb1d1ce4fc61bf79fd972280f4834e56a4b56974958903e74bd1d19789c93d6bdebe8bead9b5fca8ad26d4c35967760cf0517da42ebfeb35d
data/lib/bitcoin/block.rb CHANGED
@@ -17,6 +17,10 @@ module Bitcoin
17
17
  header.hash
18
18
  end
19
19
 
20
+ def block_hash
21
+ header.block_hash
22
+ end
23
+
20
24
  # calculate block weight
21
25
  def weight
22
26
  stripped_size * (WITNESS_SCALE_FACTOR - 1) + size
@@ -41,7 +45,7 @@ module Bitcoin
41
45
 
42
46
  # calculate merkle root from tx list.
43
47
  def calculate_merkle_root
44
- Bitcoin::MerkleTree.build_from_leaf(transactions.map(&:hash)).merkle_root
48
+ Bitcoin::MerkleTree.build_from_leaf(transactions.map(&:tx_hash)).merkle_root
45
49
  end
46
50
 
47
51
  # check the witness commitment in coinbase tx matches witness commitment calculated from tx list.
@@ -36,14 +36,17 @@ module Bitcoin
36
36
  (mantissa * 2 ** (8 * (exponent - 3)))
37
37
  end
38
38
 
39
- # block hash(little endian)
40
39
  def hash
40
+ calc_hash.to_i(16)
41
+ end
42
+
43
+ def block_hash
41
44
  calc_hash
42
45
  end
43
46
 
44
47
  # block hash(big endian)
45
48
  def block_id
46
- hash.rhex
49
+ block_hash.rhex
47
50
  end
48
51
 
49
52
  # evaluate block header
@@ -10,7 +10,7 @@ module Bitcoin
10
10
  end
11
11
 
12
12
  def merkle_root
13
- root.hash
13
+ root.value
14
14
  end
15
15
 
16
16
  def self.build_from_leaf(txids)
@@ -31,11 +31,16 @@ module Bitcoin
31
31
  flags.each do |f|
32
32
  current_node.flag = f
33
33
  if f.zero? || current_node.leaf?
34
- current_node.hash = hashes[hash_index]
34
+ current_node.value = hashes[hash_index]
35
35
  hash_index += 1
36
36
  end
37
37
  current_node = current_node.next_partial
38
- break if hash_index == hashes.size
38
+ if hash_index == hashes.size
39
+ if current_node&.leaf?
40
+ current_node.value = hashes.last
41
+ end
42
+ break
43
+ end
39
44
  end
40
45
  new(root)
41
46
  end
@@ -52,17 +57,21 @@ module Bitcoin
52
57
  nodes.first
53
58
  end
54
59
 
60
+ def find_node(value)
61
+ root.find_node(value)
62
+ end
63
+
55
64
  # node of merkle tree
56
65
  class Node
57
66
 
58
67
  attr_accessor :flag
59
- attr_accessor :hash
68
+ attr_accessor :value
60
69
  attr_accessor :parent
61
70
  attr_accessor :left
62
71
  attr_accessor :right
63
72
 
64
- def initialize(hash = nil)
65
- @hash = hash
73
+ def initialize(value = nil)
74
+ @value = value
66
75
  end
67
76
 
68
77
  def left=(node)
@@ -75,10 +84,10 @@ module Bitcoin
75
84
  @right = node
76
85
  end
77
86
 
78
- def hash
79
- return @hash if @hash
87
+ def value
88
+ return @value if @value
80
89
  self.right = left.dup unless right
81
- Bitcoin.double_sha256([left.hash + right.hash].pack('H*')).bth
90
+ Bitcoin.double_sha256([left.value + right.value].pack('H*')).bth
82
91
  end
83
92
 
84
93
  def root?
@@ -112,7 +121,25 @@ module Bitcoin
112
121
  d
113
122
  end
114
123
 
124
+ # @param target value to be found
125
+ # @return node which has same value as target. nil if this node and any children don't have same value.
126
+ def find_node(target)
127
+ return self if value == target
128
+ return nil if flag && flag.zero?
129
+ return left&.find_node(target) || right&.find_node(target)
130
+ end
131
+
132
+ def index
133
+ i = 0
134
+ d = 1
135
+ current_node = self
136
+ until current_node.root? do
137
+ i += d if current_node.parent.right == current_node
138
+ current_node = current_node.parent
139
+ d *= 2
140
+ end
141
+ i
142
+ end
115
143
  end
116
144
  end
117
-
118
145
  end
@@ -226,6 +226,7 @@ module Bitcoin
226
226
 
227
227
  def on_merkle_block(merkle_block)
228
228
  logger.info("receive merkle block message. #{merkle_block.build_json}")
229
+ peer.handle_merkle_block(merkle_block)
229
230
  end
230
231
 
231
232
  def on_cmpct_block(cmpct_block)
@@ -92,7 +92,7 @@ module Bitcoin
92
92
  def start_block_header_download
93
93
  logger.info("[#{addr}] start block header download.")
94
94
  get_headers = Bitcoin::Message::GetHeaders.new(
95
- Bitcoin.chain_params.protocol_version, [chain.latest_block.hash])
95
+ Bitcoin.chain_params.protocol_version, [chain.latest_block.block_hash])
96
96
  conn.send_message(get_headers)
97
97
  end
98
98
 
@@ -138,7 +138,7 @@ module Bitcoin
138
138
  break unless header.valid?
139
139
  entry = chain.append_header(header)
140
140
  next unless entry
141
- @best_hash = entry.hash
141
+ @best_hash = entry.block_hash
142
142
  @best_height = entry.height
143
143
  end
144
144
  pool.changed
@@ -190,6 +190,11 @@ module Bitcoin
190
190
  pool.notify_observers(:tx, tx)
191
191
  end
192
192
 
193
+ def handle_merkle_block(merkle_block)
194
+ pool.changed
195
+ pool.notify_observers(:merkleblock, merkle_block)
196
+ end
197
+
193
198
  # send ping message.
194
199
  def send_ping
195
200
  ping = Bitcoin::Message::Ping.new
@@ -20,9 +20,9 @@ module Bitcoin
20
20
  # @param [String] payload hd key path value with binary format.
21
21
  # @return [Bitcoin::PSBT::HDKeyPath]
22
22
  def self.parse_from_payload(pubkey, payload)
23
- raise 'Size of key was not the expected size for the type BIP32 keypath' unless [Bitcoin::Key::PUBLIC_KEY_SIZE, Bitcoin::Key::COMPRESSED_PUBLIC_KEY_SIZE].include?(pubkey.bytesize)
23
+ raise ArgumentError, 'Size of key was not the expected size for the type BIP32 keypath.' unless [Bitcoin::Key::PUBLIC_KEY_SIZE, Bitcoin::Key::COMPRESSED_PUBLIC_KEY_SIZE].include?(pubkey.bytesize)
24
24
  pubkey = Bitcoin::Key.new(pubkey: pubkey.bth)
25
- raise 'Invalid pubkey' unless pubkey.fully_valid_pubkey?
25
+ raise ArgumentError, 'Invalid pubkey' unless pubkey.fully_valid_pubkey?
26
26
  self.new(pubkey.pubkey, fingerprint: payload[0...4].bth, path: payload[4..-1].unpack('I*'))
27
27
  end
28
28
 
@@ -38,9 +38,11 @@ module Bitcoin
38
38
 
39
39
  case key_type
40
40
  when PSBT_IN_TYPES[:non_witness_utxo]
41
+ raise ArgumentError, 'Invalid non-witness utxo typed key.' unless key_len == 1
41
42
  raise ArgumentError, 'Duplicate Key, input non-witness utxo already provided.' if input.non_witness_utxo
42
43
  input.non_witness_utxo = Bitcoin::Tx.parse_from_payload(value)
43
44
  when PSBT_IN_TYPES[:witness_utxo]
45
+ raise ArgumentError, 'Invalid input witness utxo typed key.' unless key_len == 1
44
46
  raise ArgumentError, 'Duplicate Key, input witness utxo already provided.' if input.witness_utxo
45
47
  input.witness_utxo = Bitcoin::TxOut.parse_from_payload(value)
46
48
  when PSBT_IN_TYPES[:partial_sig]
@@ -52,21 +54,27 @@ module Bitcoin
52
54
  raise ArgumentError, 'Duplicate Key, input partial signature for pubkey already provided.' if input.partial_sigs[pubkey.pubkey]
53
55
  input.partial_sigs[pubkey.pubkey] = value
54
56
  when PSBT_IN_TYPES[:sighash]
57
+ raise ArgumentError, 'Invalid input sighash type typed key.' unless key_len == 1
55
58
  raise ArgumentError 'Duplicate Key, input sighash type already provided.' if input.sighash_type
56
59
  input.sighash_type = value.unpack('I').first
57
60
  when PSBT_IN_TYPES[:redeem_script]
61
+ raise ArgumentError, 'Invalid redeemscript typed key.' unless key_len == 1
58
62
  raise ArgumentError, 'Duplicate Key, input redeemScript already provided.' if input.redeem_script
59
63
  input.redeem_script = Bitcoin::Script.parse_from_payload(value)
60
64
  when PSBT_IN_TYPES[:witness_script]
65
+ raise ArgumentError, 'Invalid witnessscript typed key.' unless key_len == 1
61
66
  raise ArgumentError, 'Duplicate Key, input witnessScript already provided.' if input.witness_script
62
67
  input.witness_script = Bitcoin::Script.parse_from_payload(value)
63
68
  when PSBT_IN_TYPES[:bip32_derivation]
69
+ raise ArgumentError, 'Invalid bip32 typed key.' unless key_len
64
70
  raise ArgumentError, 'Duplicate Key, pubkey derivation path already provided.' if input.hd_key_paths[key.bth]
65
71
  input.hd_key_paths[key.bth] = Bitcoin::PSBT::HDKeyPath.parse_from_payload(key, value)
66
72
  when PSBT_IN_TYPES[:script_sig]
73
+ raise ArgumentError, 'Invalid final scriptsig typed key.' unless key_len == 1
67
74
  raise ArgumentError, 'Duplicate Key, input final scriptSig already provided.' if input.final_script_sig
68
75
  input.final_script_sig = Bitcoin::Script.parse_from_payload(value)
69
76
  when PSBT_IN_TYPES[:script_witness]
77
+ raise ArgumentError, 'Invalid final script witness typed key.' unless key_len == 1
70
78
  raise ArgumentError, 'Duplicate Key, input final scriptWitness already provided.' if input.final_script_witness
71
79
  input.final_script_witness = Bitcoin::ScriptWitness.parse_from_payload(value)
72
80
  else
@@ -27,9 +27,11 @@ module Bitcoin
27
27
  value = buf.read(Bitcoin.unpack_var_int_from_io(buf))
28
28
  case key_type
29
29
  when PSBT_OUT_TYPES[:redeem_script]
30
+ raise ArgumentError, 'Invalid output redeemScript typed key.' unless key_len == 1
30
31
  raise ArgumentError, 'Duplicate Key, output redeemScript already provided' if output.redeem_script
31
32
  output.redeem_script = value
32
33
  when PSBT_OUT_TYPES[:witness_script]
34
+ raise ArgumentError, 'Invalid output witnessScript typed key.' unless key_len == 1
33
35
  raise ArgumentError, 'Duplicate Key, output witnessScript already provided' if output.witness_script
34
36
  output.witness_script = value
35
37
  when PSBT_OUT_TYPES[:bip32_derivation]
@@ -40,26 +40,27 @@ module Bitcoin
40
40
 
41
41
  case key_type
42
42
  when PSBT_GLOBAL_TYPES[:unsigned_tx]
43
- raise ArgumentError, 'Duplicate Key, unsigned tx already provided' if partial_tx.tx
43
+ raise ArgumentError, 'Invalid global transaction typed key.' unless key_len == 1
44
+ raise ArgumentError, 'Duplicate Key, unsigned tx already provided.' if partial_tx.tx
44
45
  partial_tx.tx = Bitcoin::Tx.parse_from_payload(value)
45
46
  partial_tx.tx.in.each do |tx_in|
46
47
  raise ArgumentError, 'Unsigned tx does not have empty scriptSigs and scriptWitnesses.' if !tx_in.script_sig.empty? || !tx_in.script_witness.empty?
47
48
  end
48
49
  else
49
- raise ArgumentError, 'Duplicate Key, key for unknown value already provided' if partial_tx.unknowns[key]
50
+ raise ArgumentError, 'Duplicate Key, key for unknown value already provided.' if partial_tx.unknowns[key]
50
51
  partial_tx.unknowns[([key_type].pack('C') + key).bth] = value
51
52
  end
52
53
  end
53
54
 
54
- raise ArgumentError, 'No unsigned transcation was provided.' unless partial_tx.tx
55
+ raise ArgumentError, 'No unsigned transaction was provided.' unless partial_tx.tx
55
56
 
56
57
  # read input data.
57
58
  partial_tx.tx.in.each do |tx_in|
58
59
  break if buf.eof?
59
60
  input = Input.parse_from_buf(buf)
60
61
  partial_tx.inputs << input
61
- if input.non_witness_utxo && input.non_witness_utxo.hash != tx_in.prev_hash
62
- raise ArgumentError, 'Non-witness UTXO does not match outpoint hash'
62
+ if input.non_witness_utxo && input.non_witness_utxo.tx_hash != tx_in.prev_hash
63
+ raise ArgumentError, 'Non-witness UTXO does not match outpoint hash.'
63
64
  end
64
65
  end
65
66
 
@@ -110,7 +111,7 @@ module Bitcoin
110
111
  # @param [Bitcoin::Script] witness_script witness script to set input.
111
112
  # @param [Hash] hd_key_paths bip 32 hd key paths to set input.
112
113
  def update!(prev_tx, redeem_script: nil, witness_script: nil, hd_key_paths: [])
113
- prev_hash = prev_tx.hash
114
+ prev_hash = prev_tx.tx_hash
114
115
  tx.in.each_with_index do|tx_in, i|
115
116
  if tx_in.prev_hash == prev_hash
116
117
  utxo = prev_tx.out[tx_in.out_point.index]
@@ -12,7 +12,7 @@ module Bitcoin
12
12
  h[:headers] = best_block.height
13
13
  h[:bestblockhash] = best_block.header.block_id
14
14
  h[:chainwork] = best_block.header.work
15
- h[:mediantime] = node.chain.mtp(best_block.hash)
15
+ h[:mediantime] = node.chain.mtp(best_block.block_hash)
16
16
  h
17
17
  end
18
18
 
@@ -352,6 +352,11 @@ module Bitcoin
352
352
  to_payload.bytesize
353
353
  end
354
354
 
355
+ # execute script interpreter using this script for development.
356
+ def run
357
+ Bitcoin::ScriptInterpreter.eval(Bitcoin::Script.new, self.dup)
358
+ end
359
+
355
360
  # encode int value to script number hex.
356
361
  # The stacks hold byte vectors.
357
362
  # When used as numbers, byte vectors are interpreted as little-endian variable-length integers
@@ -16,14 +16,18 @@ module Bitcoin
16
16
 
17
17
  # get database key
18
18
  def key
19
- Bitcoin::Store::KEY_PREFIX[:entry] + header.hash
19
+ Bitcoin::Store::KEY_PREFIX[:entry] + header.block_hash
20
20
  end
21
21
 
22
- # block hash
23
22
  def hash
24
23
  header.hash
25
24
  end
26
25
 
26
+ # block hash
27
+ def block_hash
28
+ header.block_hash
29
+ end
30
+
27
31
  # previous block hash
28
32
  def prev_hash
29
33
  header.prev_hash
@@ -61,7 +61,7 @@ module Bitcoin
61
61
  def save_entry(entry)
62
62
  db.batch do
63
63
  db.put(entry.key ,entry.to_payload)
64
- db.put(height_key(entry.height), entry.hash)
64
+ db.put(height_key(entry.height), entry.block_hash)
65
65
  connect_entry(entry)
66
66
  end
67
67
  end
@@ -81,17 +81,15 @@ module Bitcoin
81
81
  def connect_entry(entry)
82
82
  unless entry.genesis?
83
83
  tip_block = Bitcoin::Store::ChainEntry.parse_from_payload(get_entry_payload_from_hash(best_hash))
84
- unless tip_block.hash == entry.prev_hash
85
- raise "entry(#{entry.hash}) does not reference current best block hash(#{tip_block.hash})"
84
+ unless tip_block.block_hash == entry.prev_hash
85
+ raise "entry(#{entry.block_hash}) does not reference current best block hash(#{tip_block.block_hash})"
86
86
  end
87
87
  unless tip_block.height + 1 == entry.height
88
88
  raise "block height is small than current best block."
89
89
  end
90
90
  end
91
-
92
-
93
- db.put(KEY_PREFIX[:best], entry.hash)
94
- db.put(KEY_PREFIX[:next] + entry.prev_hash, entry.hash)
91
+ db.put(KEY_PREFIX[:best], entry.block_hash)
92
+ db.put(KEY_PREFIX[:next] + entry.prev_hash, entry.block_hash)
95
93
  end
96
94
  end
97
95
 
@@ -44,17 +44,17 @@ module Bitcoin
44
44
  # @return [Bitcoin::Store::ChainEntry] appended block header entry.
45
45
  def append_header(header)
46
46
  logger.info("append header #{header.block_id}")
47
- raise "this header is invalid. #{header.hash}" unless header.valid?
47
+ raise "this header is invalid. #{header.block_hash}" unless header.valid?
48
48
  best_block = latest_block
49
49
  current_height = best_block.height
50
- if best_block.hash == header.prev_hash
50
+ if best_block.block_hash == header.prev_hash
51
51
  entry = Bitcoin::Store::ChainEntry.new(header, current_height + 1)
52
52
  db.save_entry(entry)
53
53
  entry
54
54
  else
55
- unless find_entry_by_hash(header.hash)
55
+ unless find_entry_by_hash(header.block_hash)
56
56
  # TODO implements recovery process
57
- raise "header's previous hash(#{header.prev_hash}) does not match current best block's(#{best_block.hash})."
57
+ raise "header's previous hash(#{header.prev_hash}) does not match current best block's(#{best_block.block_hash})."
58
58
  end
59
59
  end
60
60
  end
data/lib/bitcoin/tx.rb CHANGED
@@ -70,11 +70,15 @@ module Bitcoin
70
70
  end
71
71
 
72
72
  def hash
73
+ to_payload.bth.to_i(16)
74
+ end
75
+
76
+ def tx_hash
73
77
  Bitcoin.double_sha256(serialize_old_format).bth
74
78
  end
75
79
 
76
80
  def txid
77
- hash.rhex
81
+ tx_hash.rhex
78
82
  end
79
83
 
80
84
  def witness_hash
@@ -109,7 +113,7 @@ module Bitcoin
109
113
  end
110
114
 
111
115
  def ==(other)
112
- hash == other.hash
116
+ to_payload == other.to_payload
113
117
  end
114
118
 
115
119
  # serialize tx with old tx format
@@ -49,7 +49,7 @@ module Bitcoin
49
49
 
50
50
  # check proof of work
51
51
  def check_block_header(header, state)
52
- header.hash
52
+ header.block_hash
53
53
  header.bits
54
54
 
55
55
  end
@@ -1,3 +1,3 @@
1
1
  module Bitcoin
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.2"
3
3
  end
@@ -5,8 +5,14 @@ module OpenAssets
5
5
  # whether this output is marker output for open assets.
6
6
  def open_assets_marker?
7
7
  return false unless script_pubkey.op_return?
8
- payload = Payload.parse_from_payload(script_pubkey.op_return_data)
9
- !payload.nil?
8
+ !oa_payload.nil?
9
+ end
10
+
11
+ # get open asset payload.
12
+ # @return [OpenAssets::Payload] open asset payload.
13
+ def oa_payload
14
+ return nil unless script_pubkey.op_return?
15
+ Payload.parse_from_payload(script_pubkey.op_return_data)
10
16
  end
11
17
 
12
18
  end
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: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - azuchi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-08-02 00:00:00.000000000 Z
11
+ date: 2018-09-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ecdsa