Block class

This commit is contained in:
4tochka 2018-06-29 23:39:57 +04:00
parent 3da185c241
commit 2a18e7a6af
8 changed files with 192 additions and 42 deletions

View File

@ -4,25 +4,91 @@ from struct import pack, unpack
class Block(dict):
def __init__(self, block):
s = get_stream(block)
self["header"] = s.read(80)
self["hash"] = double_sha256(self["header"])
self["version"] = unpack("<L", s.read(4))
def __init__(self, raw_block=None, format="decoded", version=536870912, testnet=False):
if format not in ("decoded", "raw"):
raise ValueError("tx_format error, raw or decoded allowed")
self["format"] = format
self["testnet"] = testnet
self["header"] = None
self["hash"] = None
self["version"] = version
self["versionHex"] = hexlify(struct.pack(">L", version)).decode()
self["previousBlockHash"] = None
self["merkleRoot"] = None
self["tx"] = dict()
self["time"] = None
self["bits"] = None
self["nonce"] = None
self["weight"] = 0
self["size"] = 80
self["strippedSize"] = 80
self["amount"] = 0
self["height"] = None
self["difficulty"] = None
self["targetDifficulty"] = None
self["target"] = None
if raw_block is None:
return
self["size"] = len(raw_block) if isinstance(raw_block, bytes) else int(len(raw_block)/2)
s = self.get_stream(raw_block)
self["format"] = "raw"
self["version"] = unpack("<L", s.read(4))[0]
self["versionHex"] = hexlify(struct.pack(">L", self["version"])).decode()
self["previousBlockHash"] = s.read(32)
self["merkleRoot"] = s.read(32)
self["time"] = unpack("<L", s.read(4))
self["bits"] = s.read(4),
self["nonce"] = unpack("<L", s.read(4))
self["time"] = unpack("<L", s.read(4))[0]
self["bits"] = s.read(4)
self["target"] = bits_to_target(unpack("<L", self["bits"])[0])
self["targetDifficulty"] = target_to_difficulty(self["target"])
self["target"] = self["target"].to_bytes(32, byteorder="little")
self["nonce"] = unpack("<L", s.read(4))[0]
s.seek(-80, 1)
# self["tx"] = {i: Transaction(s)
# for i in range(var_int_to_int(read_var_int(s)))}
self["weight"] = 0
self["size"] = 0
self["strippedSize"] = 0
self["height"] = 0
self["difficulty"] = 0
self["targetDifficulty"] = 0
self["target"] = 0
self["header"] = s.read(80)
self["hash"] = double_sha256(self["header"])
block_target = int.from_bytes(self["hash"], byteorder="little")
self["difficulty"] = target_to_difficulty(block_target)
tx_count = var_int_to_int(read_var_int(s))
self["tx"] = {i: Transaction(s, format="raw")
for i in range(tx_count)}
for t in self["tx"].values():
self["amount"] += t["amount"]
self["strippedSize"] += t["bSize"]
self["strippedSize"] += var_int_len(tx_count)
self["weight"] = self["strippedSize"] * 3 + self["size"]
if format == "decoded":
self.decode(testnet=testnet)
def decode(self, testnet=None):
self["format"] = "decoded"
if testnet is not None:
self["testnet"] = testnet
if isinstance(self["hash"], bytes):
self["hash"] = rh2s(self["hash"])
if isinstance(self["target"], bytes):
self["target"] = rh2s(self["target"])
if isinstance(self["previousBlockHash"], bytes):
self["previousBlockHash"] = rh2s(self["previousBlockHash"])
if "nextBlockHash" in self:
if isinstance(self["nextBlockHash"], bytes):
self["nextBlockHash"] = rh2s(self["nextBlockHash"])
if isinstance(self["merkleRoot"], bytes):
self["merkleRoot"] = rh2s(self["merkleRoot"])
if isinstance(self["header"], bytes):
self["header"] = hexlify(self["header"]).decode()
if isinstance(self["bits"], bytes):
self["bits"] = rh2s(self["bits"])
for i in self["tx"]:
self["tx"][i].decode(testnet=testnet)
@staticmethod
def get_stream(stream):
if type(stream) != io.BytesIO:
if type(stream) == str:
stream = unhexlify(stream)
if type(stream) == bytes:
stream = io.BytesIO(stream)
else:
raise TypeError
return stream

View File

@ -1,3 +1,8 @@
"""
Old code will be removed
"""
import io
import json
import math

View File

@ -21,10 +21,10 @@ class Transaction(dict):
:param boolean testnet: address type for "decoded" transaction representation.
"""
def __init__(self, raw_tx=None, tx_format="decoded", version=1, lock_time=0, testnet=False):
if tx_format not in ("decoded", "raw"):
raise TypeError("tx_format error, raw or decoded allowed")
self["format"] = tx_format
def __init__(self, raw_tx=None, format="decoded", version=1, lock_time=0, testnet=False):
if format not in ("decoded", "raw"):
raise ValueError("format error, raw or decoded allowed")
self["format"] = format
self["testnet"] = testnet
self["segwit"] = False
self["txId"] = None
@ -94,7 +94,7 @@ class Transaction(dict):
for k in range(ic):
self["vIn"][k]["txInWitness"] = [stream.read(var_int_to_int(read_var_int(stream))) \
for c in range(var_int_to_int(read_var_int(stream)))]
sw_len = stream.tell() - sw + 2
sw_len = (stream.tell() - start) - sw + 2
self["lockTime"] = unpack('<L', stream.read(4))[0]
@ -282,7 +282,8 @@ class Transaction(dict):
self["format"] = "raw"
return self
def get_stream(self, stream):
@staticmethod
def get_stream(stream):
if type(stream) != io.BytesIO:
if type(stream) == str:
stream = unhexlify(stream)

View File

@ -1,13 +1,12 @@
# from .hash_functions import *
# from .integer import *
# from .address_functions import *
# from .address_class import *
# from .ecdsa import *
# from .transaction_deserialize import *
from .hash_functions import *
from .integer import *
from .address_functions import *
from .address_class import *
from .ecdsa import *
from .transaction_deserialize import *
from .transaction_constructor import *
from .sighash import *
# from .script_deserialize import *
# from .create_transaction import *
from .sighash import *
# from .block import *
from .block import *

View File

@ -104,7 +104,7 @@ class AddressClassTests(unittest.TestCase):
redeem = "5221032bfc25cf7cccc278b26473e2967b8fd403b4b544b836e71abdfebb08d8c96d6921032bfc25cf7cccc278b2" \
"6473e2967b8fd403b4b544b836e71abdfebb08d8c96d6921032bfc25cf7cccc278b26473e2967b8fd403b4b544b8" \
"36e71abdfebb08d8c96d6953ae"
a = address.ScriptAddress(redeem)
a = address.ScriptAddress(redeem, witness_version=None)
self.assertEqual(a.address, '3KCqqS6eznp3ucVPxtNkiYcVg6kQKNX9sg')

View File

@ -587,17 +587,21 @@ block_a = """00000020358d4156e298db6a1158e7796d511e7c3076ab64fd10bed03c160000000
# }
#
class BlockDeserializeTests(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("\nTesting Block class deserialization:\n")
def test_block_class(self):
block_c = "2000000000000000000029a1a0390376afd72db120d698c2d8ebc41c545c7d4bc2b9033c303dd3d09d455da1c587406820a4dd77c5aa3fcc546dcceb1becc639829c4fe6535e815a1a372b405cc0829701010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2303f88e130068747470733a5c6170692e6269746170732e636f6d20f251bec0cb000000ffffffff02c817a804000000001976a914d4e49947b9f545218cd20389244c249d3520545d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000"
block_e = "2000000000000000000029a1a0390376afd72db120d698c2d8ebc41c545c7d4bc2b9033c303dd3d09d455da1c587406820a4dd77c5aa3fcc546dcceb1becc639829c4fe65a815e531a372b405cc0829701010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2303f88e130068747470733a5c6170692e6269746170732e636f6d20f251bec0cb000000ffffffff02c817a804000000001976a914d4e49947b9f545218cd20389244c249d3520545d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000"
l = block.Block(block_a)
print(l)
assert 0
l = block.Block(block_a, format="decoded")
f = open('./test/raw_block.txt')
fc = f.readline()
qt = time.time()
bt = block.Block(fc[:-1], format="decoded")
# self.assertEqual(time.time() - qt < 1, 1)
# print(">>>",block.bits)
# print(">>>",block.hash)

File diff suppressed because one or more lines are too long

View File

@ -16,7 +16,7 @@ from pybtc import address_to_hash as address2hash160
def decode_block_tx(block):
stream = get_stream(block)
stream.seek(80)
return {i: Transaction(stream, tx_format="raw") for i in range(var_int_to_int(read_var_int(stream)))}
return {i: Transaction(stream, format="raw") for i in range(var_int_to_int(read_var_int(stream)))}
class TransactionDeserializeTests(unittest.TestCase):