Block class
This commit is contained in:
parent
3da185c241
commit
2a18e7a6af
100
pybtc/block.py
100
pybtc/block.py
@ -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
|
||||
|
||||
|
||||
@ -1,3 +1,8 @@
|
||||
"""
|
||||
Old code will be removed
|
||||
"""
|
||||
|
||||
|
||||
import io
|
||||
import json
|
||||
import math
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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 *
|
||||
@ -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')
|
||||
|
||||
|
||||
|
||||
@ -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
@ -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):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user