connector
This commit is contained in:
parent
52db561690
commit
fbbf099dbc
@ -51,11 +51,23 @@ static PyObject* crypto_double_sha256(PyObject *, PyObject* args) {
|
||||
return return_value;
|
||||
}
|
||||
|
||||
static PyObject* crypto_sha256(PyObject *, PyObject* args) {
|
||||
Py_buffer buffer;
|
||||
if (!PyArg_ParseTuple(args,"y*", &buffer)) return NULL;
|
||||
unsigned char h[CSHA256::OUTPUT_SIZE];
|
||||
CSHA256().Write((const unsigned char*)buffer.buf, buffer.len).Finalize(h);
|
||||
PyBuffer_Release(&buffer);
|
||||
PyObject *return_value = Py_BuildValue("y#", h, CSHA256::OUTPUT_SIZE);
|
||||
Py_DECREF(h);
|
||||
return return_value;
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef module_methods[] = {
|
||||
{ "__decode_base58__", (PyCFunction)crypto_decode_base58, METH_VARARGS, nullptr },
|
||||
{ "__encode_base58__", (PyCFunction)crypto_encode_base58, METH_VARARGS, nullptr },
|
||||
{ "__double_sha256__", (PyCFunction)crypto_double_sha256, METH_VARARGS, nullptr },
|
||||
{ "__sha256__", (PyCFunction)crypto_sha256, METH_VARARGS, nullptr },
|
||||
{ nullptr, nullptr, 0, nullptr }
|
||||
};
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ from pybtc.transaction import Transaction
|
||||
|
||||
|
||||
class Block(dict):
|
||||
def __init__(self, raw_block=None, format="decoded", version=536870912, testnet=False):
|
||||
def __init__(self, raw_block=None, format="decoded", version=536870912, testnet=False, keep_raw_tx=False):
|
||||
if format not in ("decoded", "raw"):
|
||||
raise ValueError("tx_format error, raw or decoded allowed")
|
||||
self["format"] = format
|
||||
@ -52,7 +52,7 @@ class Block(dict):
|
||||
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")
|
||||
self["tx"] = {i: Transaction(s, format="raw", keep_raw_tx=keep_raw_tx)
|
||||
for i in range(tx_count)}
|
||||
for t in self["tx"].values():
|
||||
self["amount"] += t["amount"]
|
||||
|
||||
@ -12,6 +12,9 @@ def __encode_base58__(h):
|
||||
def __double_sha256__(h):
|
||||
return _crypto.__double_sha256__(h)
|
||||
|
||||
def __sha256__(h):
|
||||
return _crypto.__sha256__(h)
|
||||
|
||||
|
||||
def __secp256k1_context_randomize__(seed = None):
|
||||
if seed is None:
|
||||
|
||||
@ -2,6 +2,7 @@ from hashlib import new as hashlib_new
|
||||
from hashlib import sha256 as hashlib_sha256
|
||||
from hashlib import sha512 as hashlib_sha512
|
||||
from pybtc.crypto import __double_sha256__
|
||||
from pybtc.crypto import __sha256__
|
||||
import hmac
|
||||
|
||||
bytes_from_hex = bytes.fromhex
|
||||
@ -9,7 +10,8 @@ bytes_from_hex = bytes.fromhex
|
||||
def sha256(h, hex=False):
|
||||
if isinstance(h, str):
|
||||
h = bytes_from_hex(h)
|
||||
return hashlib_sha256(h).hexdigest() if hex else hashlib_sha256(h).digest()
|
||||
# return hashlib_sha256(h).hexdigest() if hex else hashlib_sha256(h).digest()
|
||||
return __sha256__(h).hex() if hex else __sha256__(h)
|
||||
|
||||
|
||||
def double_sha256(h, hex=False):
|
||||
@ -18,6 +20,7 @@ def double_sha256(h, hex=False):
|
||||
h = bytes_from_hex(h)
|
||||
# if isinstance(h, bytearray):
|
||||
# h = bytes(h)
|
||||
# return hashlib_sha256(hashlib_sha256(h).digest()).digest()
|
||||
return __double_sha256__(h).hex() if hex else __double_sha256__(h)
|
||||
|
||||
|
||||
|
||||
@ -38,8 +38,7 @@ def parse_script(script, segwit=True):
|
||||
try:
|
||||
script = bytes_from_hex(script)
|
||||
except:
|
||||
pass
|
||||
assert isinstance(script, bytes)
|
||||
raise ValueError("hex encoded string required")
|
||||
l = len(script)
|
||||
if segwit:
|
||||
if l == 22 and script[0] == 0:
|
||||
|
||||
@ -148,9 +148,16 @@ def read_var_int(stream):
|
||||
:param stream: io.BytesIO stream.
|
||||
:return: bytes.
|
||||
"""
|
||||
read = stream.read
|
||||
l = read(1)
|
||||
return b"".join((l, read(get_var_int_len(l) - 1)))
|
||||
l = stream.read(1)
|
||||
if l[0] == 253:
|
||||
s = 3
|
||||
elif l[0] == 254:
|
||||
s = 5
|
||||
elif l[0] == 255:
|
||||
s = 9
|
||||
else:
|
||||
return l
|
||||
return b"".join((l, stream.read(s - 1)))
|
||||
|
||||
|
||||
def read_var_list(stream, data_type):
|
||||
|
||||
@ -601,7 +601,7 @@ class BlockDeserializeTests(unittest.TestCase):
|
||||
fc = f.readline()
|
||||
qt = time.time()
|
||||
bt = (
|
||||
Block(fc[:-1], format="raw"),
|
||||
Block(fc[:-1], format="raw", keep_raw_tx=False),
|
||||
)
|
||||
print("decoded block", time.time() - qt )
|
||||
import pickle
|
||||
@ -613,10 +613,10 @@ class BlockDeserializeTests(unittest.TestCase):
|
||||
print("decoded block load", time.time() - qt)
|
||||
import cProfile
|
||||
|
||||
# cProfile.run("import pybtc;"
|
||||
# "f = open('./pybtc/test/raw_block.txt');"
|
||||
# "fc = f.readline();"
|
||||
# "pybtc.Block(fc[:-1], format='decoded')")
|
||||
cProfile.run("import pybtc;"
|
||||
"f = open('./pybtc/test/raw_block.txt');"
|
||||
"fc = f.readline();"
|
||||
"pybtc.Block(fc[:-1], format='raw', keep_raw_tx=False)")
|
||||
# cProfile.run("import pybtc;"
|
||||
# "f = open('./pybtc/test/raw_block.txt');"
|
||||
# "fc = f.readline();"
|
||||
|
||||
@ -35,7 +35,8 @@ class Transaction(dict):
|
||||
:param boolean testnet: address type for "decoded" transaction representation.
|
||||
|
||||
"""
|
||||
def __init__(self, raw_tx=None, format="decoded", version=1, lock_time=0, testnet=False, auto_commit=True):
|
||||
def __init__(self, raw_tx=None, format="decoded", version=1,
|
||||
lock_time=0, testnet=False, auto_commit=True, keep_raw_tx=False):
|
||||
if format not in ("decoded", "raw"):
|
||||
raise ValueError("format error, raw or decoded allowed")
|
||||
self.auto_commit = auto_commit
|
||||
@ -64,6 +65,8 @@ class Transaction(dict):
|
||||
if raw_tx is None:
|
||||
return
|
||||
|
||||
self["rawTx"] = []
|
||||
rtx = self["rawTx"].append
|
||||
self["amount"] = 0
|
||||
sw = sw_len = 0
|
||||
stream = self.get_stream(raw_tx)
|
||||
@ -72,30 +75,48 @@ class Transaction(dict):
|
||||
tell = stream.tell
|
||||
seek = stream.seek
|
||||
# start deserialization
|
||||
self["version"] = unpack('<L', read(4))[0]
|
||||
t = read(4)
|
||||
rtx(t)
|
||||
self["version"] = unpack('<L', t)[0]
|
||||
n = read_var_int(stream)
|
||||
|
||||
rtx(n)
|
||||
if n == b'\x00':
|
||||
# segwit format
|
||||
sw = 1
|
||||
self["flag"] = read(1)
|
||||
rtx(self["flag"])
|
||||
n = read_var_int(stream)
|
||||
|
||||
rtx(n)
|
||||
# inputs
|
||||
ic = var_int_to_int(n)
|
||||
|
||||
for k in range(ic):
|
||||
self["vIn"][k] = dict()
|
||||
self["vIn"][k]["txId"] = read(32)
|
||||
self["vIn"][k]["vOut"] = unpack('<L', read(4))[0]
|
||||
self["vIn"][k]["scriptSig"] = read(var_int_to_int(read_var_int(stream)))
|
||||
self["vIn"][k]["sequence"] = unpack('<L', read(4))[0]
|
||||
|
||||
rtx(self["vIn"][k]["txId"])
|
||||
t = read(4)
|
||||
rtx(t)
|
||||
self["vIn"][k]["vOut"] = unpack('<L', t)[0]
|
||||
t = read_var_int(stream)
|
||||
rtx(t)
|
||||
self["vIn"][k]["scriptSig"] = read(var_int_to_int(t))
|
||||
rtx(self["vIn"][k]["scriptSig"])
|
||||
t = read(4)
|
||||
rtx(t)
|
||||
self["vIn"][k]["sequence"] = unpack('<L', t)[0]
|
||||
# outputs
|
||||
for k in range(var_int_to_int(read_var_int(stream))):
|
||||
t = read_var_int(stream)
|
||||
rtx(t)
|
||||
for k in range(var_int_to_int(t)):
|
||||
self["vOut"][k] = dict()
|
||||
self["vOut"][k]["value"] = unpack('<Q', read(8))[0]
|
||||
t = read(8)
|
||||
self["vOut"][k]["value"] = unpack('<Q', t)[0]
|
||||
rtx(t)
|
||||
self["amount"] += self["vOut"][k]["value"]
|
||||
self["vOut"][k]["scriptPubKey"] = read(var_int_to_int(read_var_int(stream)))
|
||||
t = read_var_int(stream)
|
||||
self["vOut"][k]["scriptPubKey"] = read(var_int_to_int(t))
|
||||
rtx(t)
|
||||
rtx(self["vOut"][k]["scriptPubKey"])
|
||||
s = parse_script(self["vOut"][k]["scriptPubKey"])
|
||||
self["vOut"][k]["nType"] = s["nType"]
|
||||
self["vOut"][k]["type"] = s["type"]
|
||||
@ -110,16 +131,23 @@ class Transaction(dict):
|
||||
if sw:
|
||||
sw = tell() - start
|
||||
for k in range(ic):
|
||||
self["vIn"][k]["txInWitness"] = [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() - start) - sw + 2
|
||||
self["vIn"][k]["txInWitness"] = []
|
||||
t = read_var_int(stream)
|
||||
rtx(t)
|
||||
for c in range(var_int_to_int(t)):
|
||||
l = read_var_int(stream)
|
||||
rtx(l)
|
||||
d = read(var_int_to_int(l))
|
||||
rtx(d)
|
||||
self["vIn"][k]["txInWitness"].append(d)
|
||||
|
||||
self["lockTime"] = unpack('<L', read(4))[0]
|
||||
sw_len = (stream.tell() - start) - sw + 2
|
||||
t = read(4)
|
||||
rtx(t)
|
||||
self["lockTime"] = unpack('<L', t)[0]
|
||||
|
||||
end = tell()
|
||||
seek(start)
|
||||
b = read(end - start)
|
||||
self["rawTx"] = b
|
||||
self["rawTx"] = b"".join(self["rawTx"])
|
||||
self["size"] = end - start
|
||||
self["bSize"] = end - start - sw_len
|
||||
self["weight"] = self["bSize"] * 3 + self["size"]
|
||||
@ -132,12 +160,16 @@ class Transaction(dict):
|
||||
self["coinbase"] = False
|
||||
if sw:
|
||||
self["segwit"] = True
|
||||
self["hash"] = double_sha256(b)
|
||||
self["txId"] = double_sha256(b"%s%s%s" % (b[:4], b[6:sw],b[-4:]))
|
||||
self["hash"] = double_sha256(self["rawTx"])
|
||||
self["txId"] = double_sha256(b"".join((self["rawTx"][:4], self["rawTx"][6:sw], self["rawTx"][-4:])))
|
||||
else:
|
||||
self["segwit"] = False
|
||||
self["txId"] = double_sha256(b)
|
||||
self["txId"] = double_sha256(self["rawTx"])
|
||||
self["hash"] = self["txId"]
|
||||
if not keep_raw_tx:
|
||||
self["rawTx"] = None
|
||||
else:
|
||||
self["rawTx"] = None
|
||||
if self["format"] == "decoded":
|
||||
self.decode()
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user