Browse Source

Generic header length

If header lengths change in the future, only one function needs
to change in coins.py.
master
Neil Booth 8 years ago
parent
commit
7f9cb9cd9d
  1. 22
      lib/coins.py
  2. 10
      server/block_processor.py
  3. 24
      server/db.py

22
lib/coins.py

@ -34,7 +34,6 @@ class Coin(object):
REORG_LIMIT=200
# Not sure if these are coin-specific
HEADER_LEN = 80
RPC_URL_REGEX = re.compile('.+@[^:]+(:[0-9]+)?')
VALUE_PER_COIN = 100000000
CHUNK_SIZE=2016
@ -191,9 +190,24 @@ class Coin(object):
return header[4:36]
@classmethod
def read_block(cls, block):
'''Return a tuple (header, tx_hashes, txs) given a raw block.'''
header, rest = block[:cls.HEADER_LEN], block[cls.HEADER_LEN:]
def header_offset(cls, height):
'''Given a header height return its offset in the headers file.
If header sizes change at some point, this is the only code
that needs updating.'''
return height * 80
@classmethod
def header_len(cls, height):
'''Given a header height return its length.'''
return cls.header_offset(height + 1) - cls.header_offset(height)
@classmethod
def read_block(cls, block, height):
'''Return a tuple (header, tx_hashes, txs) given a raw block at
the given height.'''
hlen = cls.header_len(height)
header, rest = block[:hlen], block[hlen:]
return (header, ) + Deserializer(rest).read_block()
@classmethod

10
server/block_processor.py

@ -128,7 +128,7 @@ class Prefetcher(LoggedClass):
# Strip the unspendable genesis coinbase
if first == 0:
blocks[0] = blocks[0][:self.coin.HEADER_LEN] + bytes(1)
blocks[0] = blocks[0][:self.coin.header_len(0)] + bytes(1)
# Update our recent average block size estimate
size = sum(len(block) for block in blocks)
@ -503,7 +503,7 @@ class BlockProcessor(server.db.DB):
self.tx_counts.append(prior_tx_count + len(txs))
def advance_block(self, block, touched):
header, tx_hashes, txs = self.coin.read_block(block)
header, tx_hashes, txs = self.coin.read_block(block, self.height + 1)
if self.tip != self.coin.header_prevhash(header):
raise ChainReorg
@ -562,13 +562,13 @@ class BlockProcessor(server.db.DB):
def backup_blocks(self, blocks, touched):
'''Backup the blocks and flush.
The blocks should be in order of decreasing height.
A flush is performed once the blocks are backed up.
The blocks should be in order of decreasing height, starting at.
self.height. A flush is performed once the blocks are backed up.
'''
self.assert_flushed()
for block in blocks:
header, tx_hashes, txs = self.coin.read_block(block)
header, tx_hashes, txs = self.coin.read_block(block, self.height)
header_hash = self.coin.header_hash(header)
if header_hash != self.tip:
raise ChainError('backup block {} is not tip {} at height {:,d}'

24
server/db.py

@ -258,7 +258,7 @@ class DB(util.LoggedClass):
assert len(hashes) // 32 == txs_done
# Write the headers, tx counts, and tx hashes
offset = (fs_height + 1) * self.coin.HEADER_LEN
offset = self.coin.header_offset(fs_height + 1)
self.headers_file.write(offset, b''.join(headers))
offset = (fs_height + 1) * self.tx_counts.itemsize
self.tx_counts_file.write(offset,
@ -274,9 +274,9 @@ class DB(util.LoggedClass):
raise self.DBError('{:,d} headers starting at {:,d} not on disk'
.format(count, start))
if disk_count:
header_len = self.coin.HEADER_LEN
offset = start * header_len
return self.headers_file.read(offset, disk_count * header_len)
offset = self.coin.header_offset(start)
size = self.coin.header_offset(start + disk_count) - offset
return self.headers_file.read(offset, size)
return b''
def fs_tx_hash(self, tx_num):
@ -288,14 +288,18 @@ class DB(util.LoggedClass):
tx_hash = None
else:
tx_hash = self.hashes_file.read(tx_num * 32, 32)
return tx_hash, height
return tx_hash, tx_height
def fs_block_hashes(self, height, count):
headers = self.read_headers(height, count)
# FIXME: move to coins.py
hlen = self.coin.HEADER_LEN
return [self.coin.header_hash(header)
for header in util.chunks(headers, hlen)]
headers_concat = self.read_headers(height, count)
offset = 0
headers = []
for n in range(count):
hlen = self.coin.header_len(height + n)
headers.append(headers_concat[offset:offset + hlen])
offset += hlen
return [self.coin.header_hash(header) for header in headers]
@staticmethod
def _resolve_limit(limit):

Loading…
Cancel
Save