Class: Bitcoin::Protocol::AuxPow

Inherits:
Object
  • Object
show all
Defined in:
lib/bitcoin/protocol/aux_pow.rb

Overview

Auxiliary Proof-of-Work for merge-mined blockchains See en.bitcoin.it/wiki/Merged_mining_specification.

The AuxPow contains all data needed to verify that the child block was included in the parents coinbase transaction, and the parent satisfies the difficulty target.

It encodes the parent_block header, and its coinbase_tx. The coinbase_branch and coinbase_index can be used to recalculate the parent blocks merkle root and prove the coinbase transaction is really included in it. The chain_branch and chain_index are used to link the child block to the merkle root contained in the coinbase_tx. (So there can be more than one merge-mined chain)

TODO: decode merged-mining data from coinbase_tx

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data) ⇒ AuxPow

Returns a new instance of AuxPow.



43
44
45
# File 'lib/bitcoin/protocol/aux_pow.rb', line 43

def initialize(data)
  parse_data data if data
end

Instance Attribute Details

#block_hashObject

Hash of the parent block header



26
27
28
# File 'lib/bitcoin/protocol/aux_pow.rb', line 26

def block_hash
  @block_hash
end

#chain_branchObject

Merkle branch linking the child block to the coinbase_tx



35
36
37
# File 'lib/bitcoin/protocol/aux_pow.rb', line 35

def chain_branch
  @chain_branch
end

#chain_indexObject

Index of the child block in the chain merkle tree



38
39
40
# File 'lib/bitcoin/protocol/aux_pow.rb', line 38

def chain_index
  @chain_index
end

#coinbase_branchObject

Merkle branch linking the coinbase_tx to the parent_block



29
30
31
# File 'lib/bitcoin/protocol/aux_pow.rb', line 29

def coinbase_branch
  @coinbase_branch
end

#coinbase_indexObject

Index of the coinbase_tx in the parent blocks merkle tree



32
33
34
# File 'lib/bitcoin/protocol/aux_pow.rb', line 32

def coinbase_index
  @coinbase_index
end

#coinbase_txObject

Coinbase transaction of the parent block, linking to the child block



23
24
25
# File 'lib/bitcoin/protocol/aux_pow.rb', line 23

def coinbase_tx
  @coinbase_tx
end

#parent_blockObject

Parent block header



41
42
43
# File 'lib/bitcoin/protocol/aux_pow.rb', line 41

def parent_block
  @parent_block
end

Class Method Details

.from_hash(h) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/bitcoin/protocol/aux_pow.rb', line 95

def self.from_hash(h)
  aux_pow = new(nil)
  aux_pow.instance_eval do
    @coinbase_tx = P::Tx.from_hash(h['coinbase_tx'])
    @block_hash = h['block_hash'].htb
    @coinbase_branch = h['coinbase_branch']
    @coinbase_index = h['coinbase_index']
    @chain_branch = h['chain_branch']
    @chain_index = h['chain_index']
    @parent_block = P::Block.from_hash(h['parent_block'])
  end
  aux_pow
end

Instance Method Details

#parse_data(data) ⇒ Object



47
48
49
50
51
# File 'lib/bitcoin/protocol/aux_pow.rb', line 47

def parse_data(data)
  buf = StringIO.new(data)
  parse_data_from_io(buf)
  buf.eof? ? '' : buf.read
end

#parse_data_from_io(data) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/bitcoin/protocol/aux_pow.rb', line 53

def parse_data_from_io(data)
  @coinbase_tx = P::Tx.new(nil)
  @coinbase_tx.parse_data_from_io(data)

  @block_hash = data.read(32)
  coinbase_branch_count = P.unpack_var_int_from_io(data)

  @coinbase_branch = []
  coinbase_branch_count.times do
    break if data.eof?
    @coinbase_branch << data.read(32).reverse.hth
  end

  @coinbase_index = data.read(4).unpack('I')[0]

  @chain_branch = []
  chain_branch_count = P.unpack_var_int_from_io(data)
  chain_branch_count.times do
    break if data.eof?
    @chain_branch << data.read(32).reverse.hth
  end

  @chain_index = data.read(4).unpack('I')[0]
  block = data.read(80)
  @parent_block = P::Block.new(block)

  data
end

#to_hashObject



109
110
111
112
113
114
115
116
117
# File 'lib/bitcoin/protocol/aux_pow.rb', line 109

def to_hash
  { 'coinbase_tx' => @coinbase_tx.to_hash,
    'block_hash' => @block_hash.hth,
    'coinbase_branch' => @coinbase_branch,
    'coinbase_index' => @coinbase_index,
    'chain_branch' => @chain_branch,
    'chain_index' => @chain_index,
    'parent_block' => @parent_block.to_hash }
end

#to_payloadObject



82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/bitcoin/protocol/aux_pow.rb', line 82

def to_payload
  payload = @coinbase_tx.to_payload
  payload << @block_hash
  payload << P.pack_var_int(@coinbase_branch.count)
  payload << @coinbase_branch.map(&:htb).map(&:reverse).join
  payload << [@coinbase_index].pack('I')
  payload << P.pack_var_int(@chain_branch.count)
  payload << @chain_branch.map(&:htb).map(&:reverse).join
  payload << [@chain_index].pack('I')
  payload << @parent_block.to_payload
  payload
end