Fixed headers and verification
This commit is contained in:
parent
34c8ded449
commit
eb831374e5
|
@ -3,6 +3,7 @@
|
||||||
<component name="NewModuleRootManager">
|
<component name="NewModuleRootManager">
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/pkg" isTestSource="false" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Python 3.6 (electrum)" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="Python 3.6 (electrum)" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
|
|
@ -87,9 +87,6 @@ class NetworkConstants:
|
||||||
cls.CHECKPOINTS = read_json('checkpoints.json', [])
|
cls.CHECKPOINTS = read_json('checkpoints.json', [])
|
||||||
cls.EQUIHASH_N = 200
|
cls.EQUIHASH_N = 200
|
||||||
cls.EQUIHASH_K = 9
|
cls.EQUIHASH_K = 9
|
||||||
|
|
||||||
cls.HEADERS_URL = "http://35.224.186.7/headers00"
|
|
||||||
|
|
||||||
cls.CHUNK_SIZE = 200
|
cls.CHUNK_SIZE = 200
|
||||||
|
|
||||||
# https://github.com/z-classic/zclassic/blob/master/src/chainparams.cpp#L234
|
# https://github.com/z-classic/zclassic/blob/master/src/chainparams.cpp#L234
|
||||||
|
@ -109,9 +106,6 @@ class NetworkConstants:
|
||||||
cls.EQUIHASH_K = 9
|
cls.EQUIHASH_K = 9
|
||||||
cls.CHUNK_SIZE = 200
|
cls.CHUNK_SIZE = 200
|
||||||
|
|
||||||
cls.HEADERS_URL = "http://35.224.186.7/headers00" #TODO
|
|
||||||
|
|
||||||
|
|
||||||
NetworkConstants.set_mainnet()
|
NetworkConstants.set_mainnet()
|
||||||
|
|
||||||
################################## transactions
|
################################## transactions
|
||||||
|
@ -256,7 +250,7 @@ def push_script(x):
|
||||||
# ZCASH specific utils methods
|
# ZCASH specific utils methods
|
||||||
# https://github.com/zcash/zcash/blob/master/qa/rpc-tests/test_framework/mininode.py
|
# https://github.com/zcash/zcash/blob/master/qa/rpc-tests/test_framework/mininode.py
|
||||||
|
|
||||||
BASIC_HEADER_SIZE = 140
|
HEADER_SIZE = 1487
|
||||||
|
|
||||||
hash_to_str = lambda x: bytes(reversed(x)).hex()
|
hash_to_str = lambda x: bytes(reversed(x)).hex()
|
||||||
str_to_hash = lambda x: bytes(reversed(bytes.fromhex(x)))
|
str_to_hash = lambda x: bytes(reversed(bytes.fromhex(x)))
|
||||||
|
|
|
@ -50,6 +50,7 @@ def serialize_header(res):
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def deserialize_header(f, height):
|
def deserialize_header(f, height):
|
||||||
|
f = BytesIO(f)
|
||||||
h = {}
|
h = {}
|
||||||
h['version'] = struct.unpack("<I", f.read(4))[0]
|
h['version'] = struct.unpack("<I", f.read(4))[0]
|
||||||
h['prev_block_hash'] = hash_to_str(f.read(32))
|
h['prev_block_hash'] = hash_to_str(f.read(32))
|
||||||
|
@ -62,6 +63,19 @@ def deserialize_header(f, height):
|
||||||
h['block_height'] = height
|
h['block_height'] = height
|
||||||
return h
|
return h
|
||||||
|
|
||||||
|
# def deserialize_header(f, height):
|
||||||
|
# h = {}
|
||||||
|
# h['version'] = struct.unpack("<I", f.read(4))[0]
|
||||||
|
# h['prev_block_hash'] = hash_to_str(f.read(32))
|
||||||
|
# h['merkle_root'] = hash_to_str(f.read(32))
|
||||||
|
# h['hash_reserved'] = hash_to_str(f.read(32))
|
||||||
|
# h['timestamp'] = struct.unpack("<I", f.read(4))[0]
|
||||||
|
# h['bits'] = struct.unpack("<I", f.read(4))[0]
|
||||||
|
# h['nonce'] = hash_to_str(f.read(32))
|
||||||
|
# h['n_solution'] = base64.b64encode(bytes(deser_char_vector(f))).decode('utf8')
|
||||||
|
# h['block_height'] = height
|
||||||
|
# return h
|
||||||
|
|
||||||
def sha256_header(header):
|
def sha256_header(header):
|
||||||
return uint256_from_bytes(Hash(serialize_header(header)))
|
return uint256_from_bytes(Hash(serialize_header(header)))
|
||||||
|
|
||||||
|
@ -161,24 +175,7 @@ class Blockchain(util.PrintError):
|
||||||
|
|
||||||
def update_size(self):
|
def update_size(self):
|
||||||
p = self.path()
|
p = self.path()
|
||||||
self._size = 0
|
self._size = os.path.getsize(p)//bitcoin.HEADER_SIZE if os.path.exists(p) else 0
|
||||||
if os.path.exists(p):
|
|
||||||
with open(p, 'rb') as f:
|
|
||||||
eof = f.seek(0, 2)
|
|
||||||
f.seek(0, 0)
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
f.seek(bitcoin.BASIC_HEADER_SIZE, 1)
|
|
||||||
vs = read_vector_size(f)
|
|
||||||
f.seek(vs, 1)
|
|
||||||
if f.tell() <= eof:
|
|
||||||
self._size += 1
|
|
||||||
if f.tell() >= eof:
|
|
||||||
break
|
|
||||||
except:
|
|
||||||
import traceback
|
|
||||||
traceback.print_exc()
|
|
||||||
break
|
|
||||||
|
|
||||||
def verify_header(self, header, prev_header):
|
def verify_header(self, header, prev_header):
|
||||||
if prev_header:
|
if prev_header:
|
||||||
|
@ -196,16 +193,16 @@ class Blockchain(util.PrintError):
|
||||||
raise BaseException("Equihash invalid")
|
raise BaseException("Equihash invalid")
|
||||||
|
|
||||||
def verify_chunk(self, index, data):
|
def verify_chunk(self, index, data):
|
||||||
data = BytesIO(data)
|
num = len(data) // bitcoin.HEADER_SIZE
|
||||||
prev_header = None
|
prev_header = None
|
||||||
if index != 0:
|
if index != 0:
|
||||||
prev_header = self.read_header(index * NetworkConstants.CHUNK_SIZE - 1)
|
prev_header = self.read_header(index * NetworkConstants.CHUNK_SIZE - 1)
|
||||||
while True:
|
|
||||||
try:
|
for i in range(num):
|
||||||
header = self.deserialize_header(data, index * NetworkConstants.CHUNK_SIZE + i)
|
raw_header = data[i*bitcoin.HEADER_SIZE:(i+1) * bitcoin.HEADER_SIZE]
|
||||||
except:
|
header = deserialize_header(raw_header, index*NetworkConstants.CHUNK_SIZE + i)
|
||||||
break
|
if header.get('block_height') != 0:
|
||||||
self.verify_header(header, prev_header)
|
self.verify_header(header, prev_header)
|
||||||
prev_header = header
|
prev_header = header
|
||||||
|
|
||||||
def path(self):
|
def path(self):
|
||||||
|
@ -215,13 +212,11 @@ class Blockchain(util.PrintError):
|
||||||
|
|
||||||
def save_chunk(self, index, chunk):
|
def save_chunk(self, index, chunk):
|
||||||
filename = self.path()
|
filename = self.path()
|
||||||
height = index * NetworkConstants.CHUNK_SIZE - self.checkpoint
|
d = (index * NetworkConstants.CHUNK_SIZE - self.checkpoint) * bitcoin.HEADER_SIZE
|
||||||
with open(filename, 'rb') as f:
|
|
||||||
d = self._height_to_offset(f, height)
|
|
||||||
if d < 0:
|
if d < 0:
|
||||||
chunk = chunk[-d:]
|
chunk = chunk[-d:]
|
||||||
d = 0
|
d = 0
|
||||||
self.write(chunk, height, index > len(self.checkpoints))
|
self.write(chunk, d)
|
||||||
self.swap_with_parent()
|
self.swap_with_parent()
|
||||||
|
|
||||||
def swap_with_parent(self):
|
def swap_with_parent(self):
|
||||||
|
@ -237,14 +232,11 @@ class Blockchain(util.PrintError):
|
||||||
with open(self.path(), 'rb') as f:
|
with open(self.path(), 'rb') as f:
|
||||||
my_data = f.read()
|
my_data = f.read()
|
||||||
with open(parent.path(), 'rb') as f:
|
with open(parent.path(), 'rb') as f:
|
||||||
self._height_to_offset
|
f.seek((checkpoint - parent.checkpoint)*bitcoin.HEADER_SIZE)
|
||||||
offset = self._height_to_offset(f, checkpoint - parent.checkpoint)
|
parent_data = f.read(parent_branch_size*bitcoin.HEADER_SIZE)
|
||||||
length = self._height_to_offset(f, parent_branch_size, offset)
|
|
||||||
f.seek(offset)
|
|
||||||
parent_data = f.read(length)
|
|
||||||
|
|
||||||
self.write(parent_data, 0)
|
self.write(parent_data, 0)
|
||||||
parent.write(my_data, checkpoint - parent.checkpoint)
|
parent.write(my_data, (checkpoint - parent.checkpoint)*bitcoin.HEADER_SIZE)
|
||||||
# store file path
|
# store file path
|
||||||
for b in blockchains.values():
|
for b in blockchains.values():
|
||||||
b.old_path = b.path()
|
b.old_path = b.path()
|
||||||
|
@ -262,42 +254,25 @@ class Blockchain(util.PrintError):
|
||||||
blockchains[self.checkpoint] = self
|
blockchains[self.checkpoint] = self
|
||||||
blockchains[parent.checkpoint] = parent
|
blockchains[parent.checkpoint] = parent
|
||||||
|
|
||||||
def _height_to_offset(self, f, height, start=0):
|
def write(self, data, offset):
|
||||||
pos = f.tell()
|
|
||||||
eof = f.seek(0, 2)
|
|
||||||
f.seek(start, 0)
|
|
||||||
for i in range(height):
|
|
||||||
f.seek(bitcoin.BASIC_HEADER_SIZE, 1)
|
|
||||||
vs = read_vector_size(f)
|
|
||||||
f.seek(vs, 1)
|
|
||||||
if f.tell() > eof:
|
|
||||||
raise Exception('Out of file')
|
|
||||||
elif f.tell() == eof:
|
|
||||||
break
|
|
||||||
result = f.tell()
|
|
||||||
f.seek(pos, 0)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def write(self, data, delta, truncate=False):
|
|
||||||
filename = self.path()
|
filename = self.path()
|
||||||
with self.lock:
|
with self.lock:
|
||||||
with open(filename, 'rb+') as f:
|
with open(filename, 'rb+') as f:
|
||||||
eof = f.seek(0, 2)
|
if offset != self._size*bitcoin.HEADER_SIZE:
|
||||||
offset = self._height_to_offset(f, delta)
|
f.seek(offset)
|
||||||
f.seek(offset)
|
|
||||||
if truncate and offset < eof:
|
|
||||||
f.truncate()
|
f.truncate()
|
||||||
|
f.seek(offset)
|
||||||
f.write(data)
|
f.write(data)
|
||||||
f.flush()
|
f.flush()
|
||||||
os.fsync(f.fileno())
|
os.fsync(f.fileno())
|
||||||
self.update_size()
|
self.update_size()
|
||||||
|
|
||||||
def save_header(self, header):
|
def save_header(self, header):
|
||||||
self.print_error("save_header", header.get('block_height'))
|
|
||||||
delta = header.get('block_height') - self.checkpoint
|
delta = header.get('block_height') - self.checkpoint
|
||||||
data = serialize_header(header)
|
data = serialize_header(header)
|
||||||
assert delta == self.size()
|
assert delta == self.size()
|
||||||
self.write(data, delta)
|
assert len(data) == bitcoin.HEADER_SIZE
|
||||||
|
self.write(data, delta*bitcoin.HEADER_SIZE)
|
||||||
self.swap_with_parent()
|
self.swap_with_parent()
|
||||||
|
|
||||||
def read_header(self, height):
|
def read_header(self, height):
|
||||||
|
@ -313,12 +288,9 @@ class Blockchain(util.PrintError):
|
||||||
name = self.path()
|
name = self.path()
|
||||||
if os.path.exists(name):
|
if os.path.exists(name):
|
||||||
with open(name, 'rb') as f:
|
with open(name, 'rb') as f:
|
||||||
for i in range(delta):
|
f.seek(delta * bitcoin.HEADER_SIZE)
|
||||||
f.seek(bitcoin.BASIC_HEADER_SIZE, 1)
|
h = f.read(bitcoin.HEADER_SIZE)
|
||||||
vs = read_vector_size(f)
|
return deserialize_header(h, height)
|
||||||
f.seek(vs, 1)
|
|
||||||
h = deserialize_header(f, height)
|
|
||||||
return h
|
|
||||||
|
|
||||||
def get_hash(self, height):
|
def get_hash(self, height):
|
||||||
return self.hash_header(self.read_header(height))
|
return self.hash_header(self.read_header(height))
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
{
|
{
|
||||||
"zcl-electrum.com": {"s":"50002"},
|
"zcl-electrum.com": {"s":"50003"}
|
||||||
"35.224.186.7": {"t":"50001", "s":"50002"},
|
|
||||||
|
|
||||||
"188.243.70.5": {"t":"51001", "s":"51002"}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue