Skip to content

Commit

Permalink
Namecoin / AuxPoW: Support deserializing headers with trailing data; …
Browse files Browse the repository at this point in the history
…support verifying chunks of variable-length headers.
  • Loading branch information
JeremyRand committed Jun 30, 2018
1 parent 2fae42f commit eba586d
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 13 deletions.
15 changes: 10 additions & 5 deletions lib/auxpow.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def auxpow_active(base_header):

return height_allows_auxpow and version_allows_auxpow

def deserialize_auxpow_header(base_header, s):
def deserialize_auxpow_header(base_header, s, expect_trailing_data=False):
auxpow_header = {}

# Chain ID is the top 16 bits of the 32-bit version.
Expand All @@ -81,14 +81,19 @@ def deserialize_auxpow_header(base_header, s):
auxpow_header['coinbase_merkle_branch'], auxpow_header['coinbase_merkle_index'], s = deserialize_merkle_branch(s)
auxpow_header['chain_merkle_branch'], auxpow_header['chain_merkle_index'], s = deserialize_merkle_branch(s)

# Finally there's the parent header. Deserialize it.
# deserialize_header will error if there's any trailing data,
# so we don't need to check it here.
auxpow_header['parent_header'] = electrum_nmc.blockchain.deserialize_header(s, 1)
# Finally there's the parent header. Deserialize it, along with any
# trailing data if requested.
if expect_trailing_data:
auxpow_header['parent_header'], trailing_data = electrum_nmc.blockchain.deserialize_header(s, 1, expect_trailing_data=expect_trailing_data)
else:
auxpow_header['parent_header'] = electrum_nmc.blockchain.deserialize_header(s, 1, expect_trailing_data=expect_trailing_data)
# The parent block header doesn't have any block height,
# so delete that field. (We used 1 as a dummy value above.)
del auxpow_header['parent_header']['block_height']

if expect_trailing_data:
return auxpow_header, trailing_data

return auxpow_header

# Copied from merkle_branch_from_string in https://github.com/electrumalt/electrum-doge/blob/f74312822a14f59aa8d50186baff74cade449ccd/lib/blockchain.py#L622
Expand Down
26 changes: 18 additions & 8 deletions lib/blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def serialize_header(res):
+ int_to_hex(int(res.get('nonce')), 4)
return s

def deserialize_header(s, height):
def deserialize_header(s, height, expect_trailing_data=False):
if not s:
raise Exception('Invalid header: {}'.format(s))
if len(s) < 80:
Expand All @@ -62,9 +62,18 @@ def deserialize_header(s, height):
h['block_height'] = height

if auxpow.auxpow_active(h):
h['auxpow'] = auxpow.deserialize_auxpow_header(h, s[80:])
elif len(s) != 80:
raise Exception('Invalid header length: {}'.format(len(s)))
if expect_trailing_data:
h['auxpow'], trailing_data = auxpow.deserialize_auxpow_header(h, s[80:], expect_trailing_data=True)
else:
h['auxpow'] = auxpow.deserialize_auxpow_header(h, s[80:])
else:
if expect_trailing_data:
trailing_data = s[80:]
elif len(s) != 80:
raise Exception('Invalid header length: {}'.format(len(s)))

if expect_trailing_data:
return h, trailing_data

return h

Expand Down Expand Up @@ -178,14 +187,15 @@ def verify_header(self, header, prev_hash, target):
raise Exception("insufficient proof of work: %s vs target %s" % (int('0x' + _hash, 16), target))

def verify_chunk(self, index, data):
num = len(data) // 80
trailing_data = data
prev_hash = self.get_hash(index * 2016 - 1)
target = self.get_target(index-1)
for i in range(num):
raw_header = data[i*80:(i+1) * 80]
header = deserialize_header(raw_header, index*2016 + i)
i = 0
while len(trailing_data) > 0:
header, trailing_data = deserialize_header(trailing_data, index*2016 + i, expect_trailing_data=True)
self.verify_header(header, prev_hash, target)
prev_hash = hash_header(header)
i = i + 1

def path(self):
d = util.get_headers_dir(self.config)
Expand Down

0 comments on commit eba586d

Please sign in to comment.