Chunk verification without saving headers locally
This commit is contained in:
parent
085cd9919e
commit
b3a21f53bc
@ -29,6 +29,13 @@ from .bitcoin import Hash, hash_encode, int_to_hex, rev_hex
|
|||||||
from . import constants
|
from . import constants
|
||||||
from .util import bfh, bh2u
|
from .util import bfh, bh2u
|
||||||
|
|
||||||
|
try:
|
||||||
|
import scrypt
|
||||||
|
getPoWHash = lambda x: scrypt.hash(x, x, N=1024, r=1, p=1, buflen=32)
|
||||||
|
except ImportError:
|
||||||
|
util.print_msg("Warning: package scrypt not available; synchronization could be very slow")
|
||||||
|
from .scrypt import scrypt_1024_1_1_80 as getPoWHash
|
||||||
|
|
||||||
|
|
||||||
HEADER_SIZE = 80 # bytes
|
HEADER_SIZE = 80 # bytes
|
||||||
MAX_TARGET = 0x00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
MAX_TARGET = 0x00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||||
@ -72,6 +79,9 @@ def hash_header(header: dict) -> str:
|
|||||||
header['prev_block_hash'] = '00'*32
|
header['prev_block_hash'] = '00'*32
|
||||||
return hash_encode(Hash(bfh(serialize_header(header))))
|
return hash_encode(Hash(bfh(serialize_header(header))))
|
||||||
|
|
||||||
|
def pow_hash_header(header):
|
||||||
|
return hash_encode(getPoWHash(bfh(serialize_header(header))))
|
||||||
|
|
||||||
|
|
||||||
blockchains = {}
|
blockchains = {}
|
||||||
blockchains_lock = threading.Lock()
|
blockchains_lock = threading.Lock()
|
||||||
@ -161,41 +171,71 @@ class Blockchain(util.PrintError):
|
|||||||
self._size = os.path.getsize(p)//HEADER_SIZE if os.path.exists(p) else 0
|
self._size = os.path.getsize(p)//HEADER_SIZE if os.path.exists(p) else 0
|
||||||
|
|
||||||
def verify_header(self, header: dict, prev_hash: str, target: int, expected_header_hash: str=None) -> None:
|
def verify_header(self, header: dict, prev_hash: str, target: int, expected_header_hash: str=None) -> None:
|
||||||
'''_hash = hash_header(header)
|
_hash = hash_header(header)
|
||||||
|
_powhash = pow_hash_header(header)
|
||||||
if expected_header_hash and expected_header_hash != _hash:
|
if expected_header_hash and expected_header_hash != _hash:
|
||||||
raise Exception("hash mismatches with expected: {} vs {}".format(expected_header_hash, _hash))
|
raise Exception("hash mismatches with expected: {} vs {}".format(expected_header_hash, _hash))
|
||||||
if prev_hash != header.get('prev_block_hash'):
|
if prev_hash != header.get('prev_block_hash'):
|
||||||
raise Exception("prev hash mismatch: %s vs %s" % (prev_hash, header.get('prev_block_hash')))
|
raise Exception("prev hash mismatch: %s vs %s" % (prev_hash, header.get('prev_block_hash')))
|
||||||
if constants.net.TESTNET:
|
if constants.net.TESTNET:
|
||||||
return
|
return
|
||||||
bits = self.target_to_bits(target)
|
#bits = self.target_to_bits(target)
|
||||||
|
bits = target
|
||||||
if bits != header.get('bits'):
|
if bits != header.get('bits'):
|
||||||
raise Exception("bits mismatch: %s vs %s" % (bits, header.get('bits')))
|
raise Exception("bits mismatch: %s vs %s" % (bits, header.get('bits')))
|
||||||
if int('0x' + _hash, 16) > target:
|
block_hash = int('0x' + _hash, 16)
|
||||||
raise Exception("insufficient proof of work: %s vs target %s" % (int('0x' + _hash, 16), target))'''
|
target_val = self.bits_to_target(bits)
|
||||||
|
if int('0x' + _powhash, 16) > target_val:
|
||||||
|
raise Exception("insufficient proof of work: %s vs target %s" % (int('0x' + _hash, 16), target_val))
|
||||||
|
|
||||||
def verify_chunk(self, index: int, data: bytes) -> None:
|
def verify_chunk(self, index: int, data: bytes) -> None:
|
||||||
num = len(data) // HEADER_SIZE
|
num = len(data) // HEADER_SIZE
|
||||||
current_header = start_height = index * 2016
|
current_header = index * 2016
|
||||||
prev_hash = self.get_hash(start_height - 1)
|
prev_hash = self.get_hash(current_header - 1)
|
||||||
headerLast = None
|
headerLast = None
|
||||||
headerFirst = None
|
headerFirst = None
|
||||||
|
capture = None
|
||||||
|
lst = []
|
||||||
for i in range(num):
|
for i in range(num):
|
||||||
target = self.get_target(current_header - 1, headerLast, headerFirst)
|
averaging_interval = self.AveragingInterval(current_header)
|
||||||
height = start_height + i
|
difficulty_interval = self.DifficultyAdjustmentInterval(current_header)
|
||||||
try:
|
if current_header < 426000:
|
||||||
expected_header_hash = self.get_hash(height)
|
target = self.get_target(current_header - 1, headerLast, headerFirst)
|
||||||
except MissingHeader:
|
try:
|
||||||
expected_header_hash = None
|
expected_header_hash = self.get_hash(current_header)
|
||||||
raw_header = data[i*HEADER_SIZE : (i+1)*HEADER_SIZE]
|
except MissingHeader:
|
||||||
header = deserialize_header(raw_header, current_header)
|
expected_header_hash = None
|
||||||
self.verify_header(header, prev_hash, target, expected_header_hash)
|
raw_header = data[i*HEADER_SIZE : (i+1)*HEADER_SIZE]
|
||||||
prev_hash = hash_header(header)
|
header = deserialize_header(raw_header, current_header)
|
||||||
headerLast = header
|
self.verify_header(header, prev_hash, target, expected_header_hash)
|
||||||
difficulty_interval = self.DifficultyAdjustmentInterval(height)
|
prev_hash = hash_header(header)
|
||||||
if height % difficulty_interval == 0:
|
headerLast = header
|
||||||
headerFirst = header
|
if current_header == 0:
|
||||||
current_header = current_header + 1
|
headerFirst = header
|
||||||
|
elif (current_header + averaging_interval + 1) % difficulty_interval == 0:
|
||||||
|
capture = header
|
||||||
|
if current_header != 0 and current_header % difficulty_interval == 0:
|
||||||
|
headerFirst = capture
|
||||||
|
if current_header >= 425993:
|
||||||
|
lst.append(headerLast)
|
||||||
|
current_header = current_header + 1
|
||||||
|
else:
|
||||||
|
if len(lst)>6:
|
||||||
|
headerFirst = lst[0]
|
||||||
|
target = self.get_target(current_header - 1, headerLast, headerFirst)
|
||||||
|
try:
|
||||||
|
expected_header_hash = self.get_hash(current_header)
|
||||||
|
except MissingHeader:
|
||||||
|
expected_header_hash = None
|
||||||
|
raw_header = data[i * HEADER_SIZE: (i + 1) * HEADER_SIZE]
|
||||||
|
header = deserialize_header(raw_header, current_header)
|
||||||
|
self.verify_header(header, prev_hash, target, expected_header_hash)
|
||||||
|
prev_hash = hash_header(header)
|
||||||
|
headerLast = header
|
||||||
|
lst.append(header)
|
||||||
|
if len(lst)>7:
|
||||||
|
lst.pop(0)
|
||||||
|
current_header = current_header + 1
|
||||||
|
|
||||||
def path(self):
|
def path(self):
|
||||||
d = util.get_headers_dir(self.config)
|
d = util.get_headers_dir(self.config)
|
||||||
@ -427,7 +467,7 @@ class Blockchain(util.PrintError):
|
|||||||
if prev_hash != header.get('prev_block_hash'):
|
if prev_hash != header.get('prev_block_hash'):
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
target = self.get_target(height // 2016 - 1)
|
target = self.get_target(height - 1)
|
||||||
except MissingHeader:
|
except MissingHeader:
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user