Class: Bitcoin::Protocol::Block
- Inherits:
-
Object
- Object
- Bitcoin::Protocol::Block
- Defined in:
- lib/bitcoin/protocol/block.rb
Constant Summary collapse
- BLOCK_VERSION_DEFAULT =
(1 << 0)
- BLOCK_VERSION_AUXPOW =
(1 << 8)
- BLOCK_VERSION_CHAIN_START =
(1 << 16)
- BLOCK_VERSION_CHAIN_END =
(1 << 30)
Instance Attribute Summary collapse
-
#aux_pow ⇒ Object
AuxPow linking the block to a merge-mined chain.
-
#bits ⇒ Object
difficulty target bits.
-
#hash ⇒ Object
block hash.
-
#mrkl_root ⇒ Object
merkle root.
-
#nonce ⇒ Object
nonce (number counted when searching for block hash matching target).
-
#payload ⇒ Object
raw protocol payload.
-
#prev_block_hash ⇒ Object
(also: #prev_block)
previous block hash.
-
#time ⇒ Object
block generation time.
-
#tx ⇒ Object
(also: #transactions)
transactions (Array of Tx).
-
#ver ⇒ Object
version (usually 1).
Class Method Summary collapse
-
.binary_from_hash(h) ⇒ Object
convert ruby hash to raw binary.
-
.binary_from_json(json_string) ⇒ Object
convert json representation to raw binary.
-
.from_file(path) ⇒ Object
read binary block from a file.
-
.from_hash(h, do_raise = true) ⇒ Object
parse ruby hash (see also #to_hash).
-
.from_json(json_string) ⇒ Object
parse json representation (see also #to_json).
-
.from_json_file(path) ⇒ Object
read json block from a file.
Instance Method Summary collapse
-
#==(other) ⇒ Object
compare to another block.
- #binary_hash ⇒ Object
-
#bip34_block_height(height = nil) ⇒ Object
introduced in block version 2 by BIP_0034 blockchain height as seen by the block itself.
-
#block_header ⇒ Object
block header binary output.
-
#block_work ⇒ Object
get the (statistical) amount of work that was needed to generate this block.
- #decimaltarget ⇒ Object
- #difficulty ⇒ Object
-
#header_info ⇒ Object
get the block header info [<version>, <prev_block>, <merkle_root>, <time>, <bits>, <nonce>, <txcount>, <size>].
-
#header_to_json(options = {:space => ''}) ⇒ Object
convert header to json representation.
- #hextarget ⇒ Object
-
#initialize(data = nil) ⇒ Block
constructor
create block from raw binary
data
. -
#parse_data(data) ⇒ Object
parse raw binary data.
-
#parse_data_from_io(buf, header_only = false) ⇒ Object
parse raw binary data.
- #prev_block=(hash) ⇒ Object
- #prev_block_hex ⇒ Object
-
#recalc_block_hash ⇒ Object
recalculate the block hash.
- #recalc_block_scrypt_hash ⇒ Object
- #recalc_mrkl_root ⇒ Object
- #size ⇒ Object
-
#to_hash(options = {}) ⇒ Object
convert to ruby hash (see also #from_hash).
-
#to_json(options = {:space => ''}, *a) ⇒ Object
convert to json representation as seen in the block explorer.
-
#to_json_file(path) ⇒ Object
write json representation to a file (see also #to_json).
-
#to_payload ⇒ Object
convert to raw binary format.
-
#verify_mrkl_root ⇒ Object
verify mrkl tree.
Constructor Details
#initialize(data = nil) ⇒ Block
create block from raw binary data
61 62 63 64 |
# File 'lib/bitcoin/protocol/block.rb', line 61 def initialize(data=nil) @tx = [] parse_data_from_io(data) if data end |
Instance Attribute Details
#aux_pow ⇒ Object
AuxPow linking the block to a merge-mined chain
43 44 45 |
# File 'lib/bitcoin/protocol/block.rb', line 43 def aux_pow @aux_pow end |
#bits ⇒ Object
difficulty target bits
31 32 33 |
# File 'lib/bitcoin/protocol/block.rb', line 31 def bits @bits end |
#hash ⇒ Object
block hash
14 15 16 |
# File 'lib/bitcoin/protocol/block.rb', line 14 def hash @hash end |
#mrkl_root ⇒ Object
merkle root
25 26 27 |
# File 'lib/bitcoin/protocol/block.rb', line 25 def mrkl_root @mrkl_root end |
#nonce ⇒ Object
nonce (number counted when searching for block hash matching target)
34 35 36 |
# File 'lib/bitcoin/protocol/block.rb', line 34 def nonce @nonce end |
#payload ⇒ Object
raw protocol payload
40 41 42 |
# File 'lib/bitcoin/protocol/block.rb', line 40 def payload @payload end |
#prev_block_hash ⇒ Object Also known as: prev_block
previous block hash
17 18 19 |
# File 'lib/bitcoin/protocol/block.rb', line 17 def prev_block_hash @prev_block_hash end |
#time ⇒ Object
block generation time
28 29 30 |
# File 'lib/bitcoin/protocol/block.rb', line 28 def time @time end |
#tx ⇒ Object Also known as: transactions
transactions (Array of Tx)
22 23 24 |
# File 'lib/bitcoin/protocol/block.rb', line 22 def tx @tx end |
#ver ⇒ Object
version (usually 1)
37 38 39 |
# File 'lib/bitcoin/protocol/block.rb', line 37 def ver @ver end |
Class Method Details
.binary_from_hash(h) ⇒ Object
convert ruby hash to raw binary
213 |
# File 'lib/bitcoin/protocol/block.rb', line 213 def self.binary_from_hash(h); from_hash(h).to_payload; end |
.binary_from_json(json_string) ⇒ Object
convert json representation to raw binary
219 |
# File 'lib/bitcoin/protocol/block.rb', line 219 def self.binary_from_json(json_string); from_json(json_string).to_payload; end |
.from_file(path) ⇒ Object
read binary block from a file
234 |
# File 'lib/bitcoin/protocol/block.rb', line 234 def self.from_file(path); new( Bitcoin::Protocol.read_binary_file(path) ); end |
.from_hash(h, do_raise = true) ⇒ Object
parse ruby hash (see also #to_hash)
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/bitcoin/protocol/block.rb', line 195 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_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, do_raise) } if h['tx'].any? (raise "Block merkle root mismatch! Block: #{h['hash']}" unless verify_mrkl_root) if do_raise end } blk end |
.from_json(json_string) ⇒ Object
parse json representation (see also #to_json)
216 |
# File 'lib/bitcoin/protocol/block.rb', line 216 def self.from_json(json_string); from_hash( JSON.load(json_string) ); end |
.from_json_file(path) ⇒ Object
read json block from a file
237 |
# File 'lib/bitcoin/protocol/block.rb', line 237 def self.from_json_file(path); from_json( Bitcoin::Protocol.read_binary_file(path) ); end |
Instance Method Details
#==(other) ⇒ Object
compare to another block
48 49 50 |
# File 'lib/bitcoin/protocol/block.rb', line 48 def ==(other) @hash == other.hash end |
#binary_hash ⇒ Object
52 53 54 |
# File 'lib/bitcoin/protocol/block.rb', line 52 def binary_hash [@hash].pack("H*") end |
#bip34_block_height(height = nil) ⇒ Object
introduced in block version 2 by BIP_0034 blockchain height as seen by the block itself. do not trust this value, instead verify with chain storage.
169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/bitcoin/protocol/block.rb', line 169 def bip34_block_height(height=nil) return nil unless @ver >= 2 if height # generate height binary buf = [height].pack("V").gsub(/\x00+$/,"") [buf.bytesize, buf].pack("Ca*") else coinbase = @tx.first.inputs.first.script_sig coinbase[1..coinbase[0].ord].ljust(4, "\x00").unpack("V").first end rescue nil end |
#block_header ⇒ Object
block header binary output
229 230 231 |
# File 'lib/bitcoin/protocol/block.rb', line 229 def block_header [@ver, @prev_block_hash, @mrkl_root, @time, @bits, @nonce, Protocol.pack_var_int(0)].pack("Va32a32VVVa*") end |
#block_work ⇒ Object
get the (statistical) amount of work that was needed to generate this block.
240 241 242 243 244 |
# File 'lib/bitcoin/protocol/block.rb', line 240 def block_work target = Bitcoin.decode_compact_bits(@bits).to_i(16) return 0 if target <= 0 (2**256) / (target + 1) end |
#decimaltarget ⇒ Object
158 159 160 |
# File 'lib/bitcoin/protocol/block.rb', line 158 def decimaltarget Bitcoin.decode_compact_bits(@bits).to_i(16) end |
#difficulty ⇒ Object
162 163 164 |
# File 'lib/bitcoin/protocol/block.rb', line 162 def difficulty Bitcoin.block_difficulty(@bits) end |
#header_info ⇒ Object
get the block header info
- <version>, <prev_block>, <merkle_root>, <time>, <bits>, <nonce>, <txcount>, <size>
122 123 124 |
# File 'lib/bitcoin/protocol/block.rb', line 122 def header_info [@ver, @prev_block_hash.reverse_hth, @mrkl_root.reverse_hth, Time.at(@time), @bits, @nonce, @tx.size, @payload.size] end |
#header_to_json(options = {:space => ''}) ⇒ Object
convert header to json representation.
222 223 224 225 226 |
# File 'lib/bitcoin/protocol/block.rb', line 222 def header_to_json( = {:space => ''}) h = to_hash %w[tx mrkl_tree].each{|k| h.delete(k) } JSON.pretty_generate( h, ) end |
#hextarget ⇒ Object
154 155 156 |
# File 'lib/bitcoin/protocol/block.rb', line 154 def hextarget Bitcoin.decode_compact_bits(@bits) end |
#parse_data(data) ⇒ Object
parse raw binary data
67 68 69 70 |
# File 'lib/bitcoin/protocol/block.rb', line 67 def parse_data(data) buf = parse_data_from_io(data) buf.eof? ? true : buf.read end |
#parse_data_from_io(buf, header_only = false) ⇒ Object
parse raw binary data
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/bitcoin/protocol/block.rb', line 73 def parse_data_from_io(buf, header_only=false) buf = buf.is_a?(String) ? StringIO.new(buf) : buf @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) end return buf if buf.eof? 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 return buf if buf.eof? t = Tx.new(nil) payload = t.parse_data_from_io(buf) @tx << t } @payload = to_payload buf end |
#prev_block=(hash) ⇒ Object
19 |
# File 'lib/bitcoin/protocol/block.rb', line 19 def prev_block=(hash); @prev_block_hash = hash; end |
#prev_block_hex ⇒ Object
56 57 58 |
# File 'lib/bitcoin/protocol/block.rb', line 56 def prev_block_hex @prev_block_hex ||= @prev_block_hash.reverse.unpack("H*")[0] end |
#recalc_block_hash ⇒ Object
recalculate the block hash
103 104 105 |
# File 'lib/bitcoin/protocol/block.rb', line 103 def recalc_block_hash @hash = Bitcoin.block_hash(@prev_block_hash.reverse_hth, @mrkl_root.reverse_hth, @time, @bits, @nonce, @ver) end |
#recalc_block_scrypt_hash ⇒ Object
107 108 109 |
# File 'lib/bitcoin/protocol/block.rb', line 107 def recalc_block_scrypt_hash @scrypt_hash = Bitcoin.block_scrypt_hash(@prev_block_hash.reverse_hth, @mrkl_root.reverse_hth, @time, @bits, @nonce, @ver) end |
#recalc_mrkl_root ⇒ Object
111 112 113 |
# File 'lib/bitcoin/protocol/block.rb', line 111 def recalc_mrkl_root @mrkl_root = Bitcoin.hash_mrkl_tree( @tx.map(&:hash) ).last.htb_reverse end |
#size ⇒ Object
150 151 152 |
# File 'lib/bitcoin/protocol/block.rb', line 150 def size payload.bytesize end |
#to_hash(options = {}) ⇒ Object
convert to ruby hash (see also #from_hash)
137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/bitcoin/protocol/block.rb', line 137 def to_hash( = {}) h = { 'hash' => @hash, 'ver' => @ver, '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() }, 'mrkl_tree' => Bitcoin.hash_mrkl_tree( @tx.map{|i| i.hash } ) } h['aux_pow'] = @aux_pow.to_hash if @aux_pow h end |
#to_json(options = {:space => ''}, *a) ⇒ Object
convert to json representation as seen in the block explorer. (see also #from_json)
184 185 186 |
# File 'lib/bitcoin/protocol/block.rb', line 184 def to_json( = {:space => ''}, *a) JSON.pretty_generate( to_hash(), ) end |
#to_json_file(path) ⇒ Object
write json representation to a file (see also #to_json)
190 191 192 |
# File 'lib/bitcoin/protocol/block.rb', line 190 def to_json_file(path) File.open(path, 'wb'){|f| f.print to_json; } end |
#to_payload ⇒ Object
convert to raw binary format
127 128 129 130 131 132 133 134 |
# File 'lib/bitcoin/protocol/block.rb', line 127 def to_payload 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 |
#verify_mrkl_root ⇒ Object
verify mrkl tree
116 117 118 |
# File 'lib/bitcoin/protocol/block.rb', line 116 def verify_mrkl_root @mrkl_root.reverse_hth == Bitcoin.hash_mrkl_tree( @tx.map(&:hash) ).last end |