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.



45
46
47
# File 'lib/bitcoin/protocol/aux_pow.rb', line 45

def initialize(data)
  parse_data (data) if data
end

Instance Attribute Details

#block_hashObject

Hash of the parent block header



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

def block_hash
  @block_hash
end

#chain_branchObject

Merkle branch linking the child block to the coinbase_tx



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

def chain_branch
  @chain_branch
end

#chain_indexObject

Index of the child block in the chain merkle tree



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

def chain_index
  @chain_index
end

#coinbase_branchObject

Merkle branch linking the coinbase_tx to the parent_block



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

def coinbase_branch
  @coinbase_branch
end

#coinbase_indexObject

Index of the coinbase_tx in the parent blocks merkle tree



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

def coinbase_index
  @coinbase_index
end

#coinbase_txObject

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



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

def coinbase_tx
  @coinbase_tx
end

#parent_blockObject

Parent block header



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

def parent_block
  @parent_block
end

Class Method Details

.from_hash(h) ⇒ Object



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

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



49
50
51
52
53
# File 'lib/bitcoin/protocol/aux_pow.rb', line 49

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

#parse_data_from_io(data) ⇒ Object



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 55

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{
    break if data.eof?
    @coinbase_branch << data.read(32).reverse.hth
  }
  @coinbase_index = data.read(4).unpack("I")[0]

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

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

  data
end

#to_hashObject



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

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



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

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