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