77import io
88import mmap
99import 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
1723g_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
8793def 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
101106def 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
715729g_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+
717765if __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