lib/bitcoin/protocol/block.rb in bitcoin-ruby-0.0.7 vs lib/bitcoin/protocol/block.rb in bitcoin-ruby-0.0.8

- old
+ new

@@ -12,11 +12,13 @@ # block hash attr_accessor :hash # previous block hash - attr_accessor :prev_block + attr_accessor :prev_block_hash + alias :prev_block :prev_block_hash + def prev_block=(hash); @prev_block_hash = hash; end # transactions (Array of Tx) attr_accessor :tx # merkle root @@ -50,11 +52,11 @@ def binary_hash [@hash].pack("H*") end def prev_block_hex - @prev_block_hex ||= @prev_block.reverse.unpack("H*")[0] + @prev_block_hex ||= @prev_block_hash.reverse.unpack("H*")[0] end # create block from raw binary +data+ def initialize(data=nil) @tx = [] @@ -68,11 +70,11 @@ end # parse raw binary data def parse_data_from_io(buf, header_only=false) buf = buf.is_a?(String) ? StringIO.new(buf) : buf - @ver, @prev_block, @mrkl_root, @time, @bits, @nonce = buf.read(80).unpack("Va32a32VVV") + @ver, @prev_block_hash, @mrkl_root, @time, @bits, @nonce = buf.read(80).unpack("Va32a32VVV") recalc_block_hash if Bitcoin.network[:auxpow_chain_id] != nil && (@ver & BLOCK_VERSION_AUXPOW) > 0 @aux_pow = AuxPow.new(nil) @aux_pow.parse_data_from_io(buf) @@ -82,11 +84,14 @@ tx_size = Protocol.unpack_var_int_from_io(buf) @tx_count = tx_size return buf if header_only - tx_size.times{ break if payload == true + tx_size.times{ + break if payload == true + return buf if buf.eof? + t = Tx.new(nil) payload = t.parse_data_from_io(buf) @tx << t } @@ -94,15 +99,15 @@ buf end # recalculate the block hash def recalc_block_hash - @hash = Bitcoin.block_hash(@prev_block.reverse_hth, @mrkl_root.reverse_hth, @time, @bits, @nonce, @ver) + @hash = Bitcoin.block_hash(@prev_block_hash.reverse_hth, @mrkl_root.reverse_hth, @time, @bits, @nonce, @ver) end def recalc_block_scrypt_hash - @scrypt_hash = Bitcoin.block_scrypt_hash(@prev_block.reverse_hth, @mrkl_root.reverse_hth, @time, @bits, @nonce, @ver) + @scrypt_hash = Bitcoin.block_scrypt_hash(@prev_block_hash.reverse_hth, @mrkl_root.reverse_hth, @time, @bits, @nonce, @ver) end def recalc_mrkl_root @mrkl_root = Bitcoin.hash_mrkl_tree( @tx.map(&:hash) ).last.htb_reverse end @@ -113,31 +118,31 @@ end # get the block header info # [<version>, <prev_block>, <merkle_root>, <time>, <bits>, <nonce>, <txcount>, <size>] def header_info - [@ver, @prev_block.reverse_hth, @mrkl_root.reverse_hth, Time.at(@time), @bits, @nonce, @tx.size, @payload.size] + [@ver, @prev_block_hash.reverse_hth, @mrkl_root.reverse_hth, Time.at(@time), @bits, @nonce, @tx.size, @payload.size] end # convert to raw binary format def to_payload - head = [@ver, @prev_block, @mrkl_root, @time, @bits, @nonce].pack("Va32a32VVV") + head = [@ver, @prev_block_hash, @mrkl_root, @time, @bits, @nonce].pack("Va32a32VVV") head << @aux_pow.to_payload if @aux_pow return head if @tx.size == 0 head << Protocol.pack_var_int(@tx.size) @tx.each{|tx| head << tx.to_payload } head end # convert to ruby hash (see also #from_hash) - def to_hash + def to_hash(options = {}) h = { 'hash' => @hash, 'ver' => @ver, - 'prev_block' => @prev_block.reverse_hth, 'mrkl_root' => @mrkl_root.reverse_hth, + 'prev_block' => @prev_block_hash.reverse_hth, 'mrkl_root' => @mrkl_root.reverse_hth, 'time' => @time, 'bits' => @bits, 'nonce' => @nonce, 'n_tx' => @tx.size, 'size' => (@payload||to_payload).bytesize, - 'tx' => @tx.map{|i| i.to_hash }, + 'tx' => @tx.map{|i| i.to_hash(options) }, 'mrkl_tree' => Bitcoin.hash_mrkl_tree( @tx.map{|i| i.hash } ) } h['aux_pow'] = @aux_pow.to_hash if @aux_pow h end @@ -175,11 +180,11 @@ end # convert to json representation as seen in the block explorer. # (see also #from_json) def to_json(options = {:space => ''}, *a) - JSON.pretty_generate( to_hash, options ) + JSON.pretty_generate( to_hash(options), options ) end # write json representation to a file # (see also #to_json) def to_json_file(path) @@ -189,16 +194,16 @@ # parse ruby hash (see also #to_hash) def self.from_hash(h, do_raise=true) blk = new(nil) blk.instance_eval{ @ver, @time, @bits, @nonce = h.values_at('ver', 'time', 'bits', 'nonce') - @prev_block, @mrkl_root = h.values_at('prev_block', 'mrkl_root').map{|i| i.htb_reverse } + @prev_block_hash, @mrkl_root = h.values_at('prev_block', 'mrkl_root').map{|i| i.htb_reverse } unless h['hash'] == recalc_block_hash raise "Block hash mismatch! Claimed: #{h['hash']}, Actual: #{@hash}" if do_raise end @aux_pow = AuxPow.from_hash(h['aux_pow']) if h['aux_pow'] - h['tx'].each{|tx| @tx << Tx.from_hash(tx) } + h['tx'].each{|tx| @tx << Tx.from_hash(tx, do_raise) } if h['tx'].any? (raise "Block merkle root mismatch! Block: #{h['hash']}" unless verify_mrkl_root) if do_raise end } blk @@ -220,10 +225,10 @@ JSON.pretty_generate( h, options ) end # block header binary output def block_header - [@ver, @prev_block, @mrkl_root, @time, @bits, @nonce, Protocol.pack_var_int(0)].pack("Va32a32VVVa*") + [@ver, @prev_block_hash, @mrkl_root, @time, @bits, @nonce, Protocol.pack_var_int(0)].pack("Va32a32VVVa*") end # read binary block from a file def self.from_file(path); new( Bitcoin::Protocol.read_binary_file(path) ); end