Skip to content

Commit cdcf94d

Browse files
author
Vizeet Srivastava
committed
working script parser for pre segwit
1 parent bbbee0e commit cdcf94d

File tree

2 files changed

+71
-19
lines changed

2 files changed

+71
-19
lines changed

blockfile_parser.py

+1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ def getBlockHeader(mptr: mmap):
9494
block_header['bits'] = bytes.decode(binascii.hexlify(mptr.read(4)[::-1]))
9595
block_header['nounce'] = bytes.decode(binascii.hexlify(mptr.read(4)[::-1]))
9696

97+
print('block_header = %s' % block_header)
9798
return block_header
9899

99100
def getTransactionCount(mptr: mmap):

script_parser.py

+70-19
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,18 @@
77
import io
88
import mmap
99
import os
10+
from blockfile_parser import getTransactionCount, getCoinbaseTransaction, getBlockHeader
11+
from leveldb_parser import getBlockIndex
12+
import json
1013

1114
#rpc_connection = AuthServiceProxy("http://%s:%[email protected]:8332"%('alice', 'passw0rd'))
1215

13-
raw_txn_str = '01000000012f03082d300efd92837d3f6d910a21d9d19e868242cfebb21198beed7b440999000000004a493046022100c0f693e024f966dc5f834324baa38426bba05460a2b3f9920989d38322176460022100c523a3aa62da26db1fc1902a93741dce3489629df18be11ba68ff9586041821601ffffffff0100f2052a010000001976a9148773ec867e322378e216eefe55bfcede5263059b88ac00000000'
16+
#raw_txn_str = '01000000012f03082d300efd92837d3f6d910a21d9d19e868242cfebb21198beed7b440999000000004a493046022100c0f693e024f966dc5f834324baa38426bba05460a2b3f9920989d38322176460022100c523a3aa62da26db1fc1902a93741dce3489629df18be11ba68ff9586041821601ffffffff0100f2052a010000001976a9148773ec867e322378e216eefe55bfcede5263059b88ac00000000'
1417
#raw_txn_str = '01000000017f950ab790838e0c05e79856d25d586823fe139e1807405a3f207ff33f9b7663010000006b483045022100d8629403cd3b49950da9293653c6279149c029e6b7b15371342d0d2ce286c8f2022078787985a644e94fd9246f6c25733336c94af5f00d9d34a07dc2f9e0987ef990012102b726d7eae11a6d5cf3b2362e773e116a6140347dcee1b2943f4a2897351e5d90ffffffff021bf03c000000000017a91469f3757380a56820abc7052867216599e575cddd8777c1ca1c000000001976a914d5f950abe0b559b2b7a7ab3d18a507ea1c3e4ac688ac00000000'
15-
txn_hash = '4269fdc239d027922dcec96f1ae283dbaff10e2d1bd49605661d091e79714956'
18+
#txn_hash = '4269fdc239d027922dcec96f1ae283dbaff10e2d1bd49605661d091e79714956'
19+
txn_hash = '8ca45aed169b0434ad5a117804cdf6eec715208d57f13396c0ba18fb5a327e30'
20+
block_hash = '0000000000000000009a8aa7b36b0e37a28bf98956097b7b844e172692e604e1'
21+
1622

1723
g_script_command_info = {}
1824

@@ -74,29 +80,28 @@ def getSigFromStack(mptr: io.BytesIO):
7480
r_size = int.from_bytes(mptr.read(1))
7581
if r_size == 0x21:
7682
mptr.read(1)
77-
r = mptr.read(0x20)
83+
r = mptr.read(r_size)
7884
s_type = int.from_bytes(mptr.read(1)) # this is always 2 and signifies int type
7985
s_size = int.from_bytes(mptr.read(1))
8086
if s_size == 0x21:
8187
mptr.read(1)
82-
s = mptr.read(0x20)
88+
s = mptr.read(s_size)
8389
sighash_type = mptr.read(1)
8490
sig = r + s + sighash_type
8591
return sig
8692

8793
def op_pushdata(mptr: io.BytesIO, code: int, stack: list):
8894
if code <= 0x4b: # push data
8995
size = code
90-
stack.append(mptr.read(size))
9196
elif code == OP_PUSHDATA1: # OP_PUSHDATA1
92-
size = int.from_bytes(mptr.read(1))
93-
stack.append(mptr.read(size))
97+
size = int.from_bytes(mptr.read(1), byteorder='big')
9498
elif code == OP_PUSHDATA2: # OP_PUSHDATA2
9599
size = int.from_bytes(mptr.read(2), byteorder='big')
96-
stack.append(mptr.read(size))
97100
elif code == OP_PUSHDATA4: # OP_PUSHDATA4
98101
size = int.from_bytes(mptr.read(4), byteorder='big')
99-
stack.append(mptr.read(size))
102+
mptr_read = mptr.read(size)
103+
print('size = %d, data = %s' % (size, bytes.decode(binascii.hexlify(mptr_read))))
104+
stack.append(mptr_read)
100105

101106
def hash256(bstr):
102107
return hashlib.sha256(hashlib.sha256(bstr).digest()).digest()
@@ -131,17 +136,21 @@ def splitSig(complete_sig: bytes):
131136
r_len = int(binascii.hexlify(sigfp.read(1)), 16)
132137
print('r_len = %d' % r_len)
133138
r = sigfp.read(r_len)
134-
print('r = %s' % bytes.decode(binascii.hexlify(r)))
135139
if r_len == 33:
136140
r = r[1:33]
141+
elif r_len < 32:
142+
r = bytes(32 - r_len) + r
143+
print('r = %s' % bytes.decode(binascii.hexlify(r)))
137144
int_type = sigfp.read(1)
138145
print('s int_type = %d' % int(binascii.hexlify(int_type), 16))
139146
s_len = int(binascii.hexlify(sigfp.read(1)), 16)
140147
print('s_len = %d' % s_len)
141148
s = sigfp.read(s_len)
142-
print('s = %s' % bytes.decode(binascii.hexlify(s)))
143149
if s_len == 33:
144-
s = r[1:33]
150+
s = s[1:33]
151+
elif s_len < 32:
152+
s = bytes(32 - s_len) + s
153+
print('s = %s' % bytes.decode(binascii.hexlify(s)))
145154
sighash_type = int(binascii.hexlify(sigfp.read(1)), 16)
146155
print('sighash_type = %x' % sighash_type)
147156
return (r, s, sighash_type)
@@ -165,7 +174,7 @@ def sigcheck(sig_b: bytes, pubkey_b: bytes, raw_txn_b: bytes):
165174
print('invalid')
166175
return 0
167176

168-
def getTxnSigned(txn: bytes, sighash_type: int):
177+
def getTxnSigned(txn: bytes, sighash_type: int, input_index: int):
169178
txn_signed_b = None
170179
if sighash_type == g_script_sig_dict['SIGHASH_ALL']:
171180
txn_signed_b = txn['version']
@@ -175,8 +184,11 @@ def getTxnSigned(txn: bytes, sighash_type: int):
175184
for index in range(getCount(txn['input_count'])):
176185
txn_signed_b += txn['input'][index]['prev_txn_hash']
177186
txn_signed_b += txn['input'][index]['prev_txn_out_index']
178-
txn_signed_b += txn['input'][index]['lock_script_size']
179-
txn_signed_b += txn['input'][index]['lock_script']
187+
if input_index == index:
188+
txn_signed_b += txn['input'][index]['lock_script_size']
189+
txn_signed_b += txn['input'][index]['lock_script']
190+
else:
191+
txn_signed_b += b'\x00'
180192
txn_signed_b += txn['input'][index]['sequence']
181193
txn_signed_b += txn['out_count']
182194
for index in range(getCount(txn['out_count'])):
@@ -494,7 +506,7 @@ def scriptParser(txn: dict, input_index: int):
494506
pubkey_b = stack.pop()
495507
complete_sig_b = stack.pop()
496508
r, s, sighash_type = splitSig(complete_sig_b)
497-
txn_signed_b = getTxnSigned(txn, sighash_type)
509+
txn_signed_b = getTxnSigned(txn, sighash_type, input_index)
498510
sig_b = r + s
499511
is_valid = sigcheck(sig_b, pubkey_b, txn_signed_b)
500512
stack.append(is_valid)
@@ -503,7 +515,7 @@ def scriptParser(txn: dict, input_index: int):
503515
pubkey_b = stack.pop()
504516
sig_b = stack.pop() # this is R, S and sig_type
505517
r, s, sighash_type = splitSig(complete_sig_b)
506-
txn_signed_b = getTxnSigned(txn, sighash_type)
518+
txn_signed_b = getTxnSigned(txn, sighash_type, input_index)
507519
sig_b = r + s
508520
is_valid = sigcheck(sig_b, pubkey_b, txn_signed_b)
509521
if is_valid == 0:
@@ -526,7 +538,7 @@ def scriptParser(txn: dict, input_index: int):
526538
for pubkey_b in pubkey_array:
527539
sig_b = sig_array[sig_index]
528540
r, s, sighash_type = splitSig(complete_sig_b)
529-
txn_signed_b = getTxnSigned(txn, sighash_type)
541+
txn_signed_b = getTxnSigned(txn, sighash_type, input_index)
530542
sig_b = r + s
531543
is_valid_sig = sigcheck(sig_b, pubkey_b, signed_txn)
532544
if is_valid_sig == 1:
@@ -554,7 +566,7 @@ def scriptParser(txn: dict, input_index: int):
554566
for pubkey_b in pubkey_array:
555567
sig_b = sig_array[sig_index]
556568
r, s, sighash_type = splitSig(complete_sig_b)
557-
txn_signed_b = getTxnSigned(txn, sighash_type)
569+
txn_signed_b = getTxnSigned(txn, sighash_type, input_index)
558570
sig_b = r + s
559571
is_valid_sig = sigcheck(sig_b, pubkey_b, signed_txn)
560572
if is_valid_sig == 1:
@@ -634,10 +646,12 @@ def get_prev_txn_info(prev_txn_hash_bigendian: str, prev_txn_out_index: int):
634646

635647
# skip all but required out
636648
for index in range(out_count):
649+
print ('prev_txn_out_index = %d, out_count = %d' % (prev_txn_out_index, out_count))
637650
if index != prev_txn_out_index:
638651
skip_satoshi = txnfp.read(8)
639652
skip_script_size = int(binascii.hexlify(txnfp.read(1)), 16)
640653
skip_script = txnfp.read(skip_script_size)
654+
continue
641655
satoshis = int(binascii.hexlify(txnfp.read(8)[::-1]), 16)
642656
lock_script_size_b = getCountBytes(txnfp)
643657
lock_script_size = getCount(lock_script_size_b)
@@ -714,6 +728,40 @@ def unlockTxn(mptr: mmap):
714728

715729
g_block_header_size = 80
716730

731+
def validate_all_transactions_of_block(block_hash_bigendian_b: bytes):
732+
jsonobj = getBlockIndex(block_hash_bigendian_b)
733+
# print('n_file = %d' % jsonobj['n_file'])
734+
print('block index = %s' % json.dumps(jsonobj))
735+
if 'data_pos' in jsonobj:
736+
block_filepath = os.path.join(blocks_path, 'blk%05d.dat' % jsonobj['n_file'])
737+
start = jsonobj['data_pos']
738+
elif 'undo_pos' in jsonobj:
739+
block_filepath = os.path.join(blocks_path, 'rev%05d.dat' % jsonobj['n_file'])
740+
start = jsonobj['undo_pos']
741+
742+
with open(block_filepath, 'rb') as block_file:
743+
# load file to memory
744+
mptr = mmap.mmap(block_file.fileno(), 0, prot=mmap.PROT_READ) #File is open read-only
745+
# skip_block_header = mptr.read(g_block_header_size)
746+
mptr.seek(start)
747+
getBlockHeader(mptr)
748+
txn_count = getTransactionCount(mptr)
749+
print('txn_count = %d' % txn_count)
750+
skip_coinbase_txn = getCoinbaseTransaction(mptr)
751+
for index in range(1, txn_count):
752+
print('XXXXXXXXXXXXXXXX txn index = %d' % index)
753+
isValid = unlockTxn(mptr)
754+
if isValid == False:
755+
print('Invalid Transaction')
756+
exit()
757+
else:
758+
print('Valid Transaction')
759+
# block = getBlock(mptr, start - 8)
760+
# print('magic number = %s' % (block['block_pre_header']['magic_number']))
761+
# next_block_hash = block['block_header']['prev_block_hash']
762+
# print('next block hash = %s, n_file = %d, height = %d' % (next_block_hash, jsonobj['n_file'], jsonobj['height']))
763+
# next_block_hash_bigendian_b = binascii.unhexlify(next_block_hash)[::-1]
764+
717765
if __name__ == '__main__':
718766
txn_hash_bigendian = binascii.unhexlify(txn_hash)[::-1]
719767
block_file_number, block_offset, txn_offset = ldb.getTxnOffset(txn_hash_bigendian)
@@ -733,3 +781,6 @@ def unlockTxn(mptr: mmap):
733781
print('Invalid Transaction')
734782
else:
735783
print('Valid Transaction')
784+
785+
block_hash_bigendian_b = binascii.unhexlify(block_hash)[::-1]
786+
validate_all_transactions_of_block(block_hash_bigendian_b)

0 commit comments

Comments
 (0)