Generic header length
If header lengths change in the future, only one function needs to change in coins.py.
This commit is contained in:
parent
c8c4199503
commit
7f9cb9cd9d
22
lib/coins.py
22
lib/coins.py
@ -34,7 +34,6 @@ class Coin(object):
|
|||||||
|
|
||||||
REORG_LIMIT=200
|
REORG_LIMIT=200
|
||||||
# Not sure if these are coin-specific
|
# Not sure if these are coin-specific
|
||||||
HEADER_LEN = 80
|
|
||||||
RPC_URL_REGEX = re.compile('.+@[^:]+(:[0-9]+)?')
|
RPC_URL_REGEX = re.compile('.+@[^:]+(:[0-9]+)?')
|
||||||
VALUE_PER_COIN = 100000000
|
VALUE_PER_COIN = 100000000
|
||||||
CHUNK_SIZE=2016
|
CHUNK_SIZE=2016
|
||||||
@ -191,9 +190,24 @@ class Coin(object):
|
|||||||
return header[4:36]
|
return header[4:36]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def read_block(cls, block):
|
def header_offset(cls, height):
|
||||||
'''Return a tuple (header, tx_hashes, txs) given a raw block.'''
|
'''Given a header height return its offset in the headers file.
|
||||||
header, rest = block[:cls.HEADER_LEN], block[cls.HEADER_LEN:]
|
|
||||||
|
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()
|
return (header, ) + Deserializer(rest).read_block()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@ -128,7 +128,7 @@ class Prefetcher(LoggedClass):
|
|||||||
|
|
||||||
# Strip the unspendable genesis coinbase
|
# Strip the unspendable genesis coinbase
|
||||||
if first == 0:
|
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
|
# Update our recent average block size estimate
|
||||||
size = sum(len(block) for block in blocks)
|
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))
|
self.tx_counts.append(prior_tx_count + len(txs))
|
||||||
|
|
||||||
def advance_block(self, block, touched):
|
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):
|
if self.tip != self.coin.header_prevhash(header):
|
||||||
raise ChainReorg
|
raise ChainReorg
|
||||||
|
|
||||||
@ -562,13 +562,13 @@ class BlockProcessor(server.db.DB):
|
|||||||
def backup_blocks(self, blocks, touched):
|
def backup_blocks(self, blocks, touched):
|
||||||
'''Backup the blocks and flush.
|
'''Backup the blocks and flush.
|
||||||
|
|
||||||
The blocks should be in order of decreasing height.
|
The blocks should be in order of decreasing height, starting at.
|
||||||
A flush is performed once the blocks are backed up.
|
self.height. A flush is performed once the blocks are backed up.
|
||||||
'''
|
'''
|
||||||
self.assert_flushed()
|
self.assert_flushed()
|
||||||
|
|
||||||
for block in blocks:
|
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)
|
header_hash = self.coin.header_hash(header)
|
||||||
if header_hash != self.tip:
|
if header_hash != self.tip:
|
||||||
raise ChainError('backup block {} is not tip {} at height {:,d}'
|
raise ChainError('backup block {} is not tip {} at height {:,d}'
|
||||||
|
|||||||
24
server/db.py
24
server/db.py
@ -258,7 +258,7 @@ class DB(util.LoggedClass):
|
|||||||
assert len(hashes) // 32 == txs_done
|
assert len(hashes) // 32 == txs_done
|
||||||
|
|
||||||
# Write the headers, tx counts, and tx hashes
|
# 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))
|
self.headers_file.write(offset, b''.join(headers))
|
||||||
offset = (fs_height + 1) * self.tx_counts.itemsize
|
offset = (fs_height + 1) * self.tx_counts.itemsize
|
||||||
self.tx_counts_file.write(offset,
|
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'
|
raise self.DBError('{:,d} headers starting at {:,d} not on disk'
|
||||||
.format(count, start))
|
.format(count, start))
|
||||||
if disk_count:
|
if disk_count:
|
||||||
header_len = self.coin.HEADER_LEN
|
offset = self.coin.header_offset(start)
|
||||||
offset = start * header_len
|
size = self.coin.header_offset(start + disk_count) - offset
|
||||||
return self.headers_file.read(offset, disk_count * header_len)
|
return self.headers_file.read(offset, size)
|
||||||
return b''
|
return b''
|
||||||
|
|
||||||
def fs_tx_hash(self, tx_num):
|
def fs_tx_hash(self, tx_num):
|
||||||
@ -288,14 +288,18 @@ class DB(util.LoggedClass):
|
|||||||
tx_hash = None
|
tx_hash = None
|
||||||
else:
|
else:
|
||||||
tx_hash = self.hashes_file.read(tx_num * 32, 32)
|
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):
|
def fs_block_hashes(self, height, count):
|
||||||
headers = self.read_headers(height, count)
|
headers_concat = self.read_headers(height, count)
|
||||||
# FIXME: move to coins.py
|
offset = 0
|
||||||
hlen = self.coin.HEADER_LEN
|
headers = []
|
||||||
return [self.coin.header_hash(header)
|
for n in range(count):
|
||||||
for header in util.chunks(headers, hlen)]
|
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
|
@staticmethod
|
||||||
def _resolve_limit(limit):
|
def _resolve_limit(limit):
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user