7
7
import io
8
8
import mmap
9
9
import os
10
+ from blockfile_parser import getTransactionCount , getCoinbaseTransaction , getBlockHeader
11
+ from leveldb_parser import getBlockIndex
12
+ import json
10
13
11
14
#rpc_connection = AuthServiceProxy("http://%s:%[email protected] :8332"%('alice', 'passw0rd'))
12
15
13
- raw_txn_str = '01000000012f03082d300efd92837d3f6d910a21d9d19e868242cfebb21198beed7b440999000000004a493046022100c0f693e024f966dc5f834324baa38426bba05460a2b3f9920989d38322176460022100c523a3aa62da26db1fc1902a93741dce3489629df18be11ba68ff9586041821601ffffffff0100f2052a010000001976a9148773ec867e322378e216eefe55bfcede5263059b88ac00000000'
16
+ # raw_txn_str = '01000000012f03082d300efd92837d3f6d910a21d9d19e868242cfebb21198beed7b440999000000004a493046022100c0f693e024f966dc5f834324baa38426bba05460a2b3f9920989d38322176460022100c523a3aa62da26db1fc1902a93741dce3489629df18be11ba68ff9586041821601ffffffff0100f2052a010000001976a9148773ec867e322378e216eefe55bfcede5263059b88ac00000000'
14
17
#raw_txn_str = '01000000017f950ab790838e0c05e79856d25d586823fe139e1807405a3f207ff33f9b7663010000006b483045022100d8629403cd3b49950da9293653c6279149c029e6b7b15371342d0d2ce286c8f2022078787985a644e94fd9246f6c25733336c94af5f00d9d34a07dc2f9e0987ef990012102b726d7eae11a6d5cf3b2362e773e116a6140347dcee1b2943f4a2897351e5d90ffffffff021bf03c000000000017a91469f3757380a56820abc7052867216599e575cddd8777c1ca1c000000001976a914d5f950abe0b559b2b7a7ab3d18a507ea1c3e4ac688ac00000000'
15
- txn_hash = '4269fdc239d027922dcec96f1ae283dbaff10e2d1bd49605661d091e79714956'
18
+ #txn_hash = '4269fdc239d027922dcec96f1ae283dbaff10e2d1bd49605661d091e79714956'
19
+ txn_hash = '8ca45aed169b0434ad5a117804cdf6eec715208d57f13396c0ba18fb5a327e30'
20
+ block_hash = '0000000000000000009a8aa7b36b0e37a28bf98956097b7b844e172692e604e1'
21
+
16
22
17
23
g_script_command_info = {}
18
24
@@ -74,29 +80,28 @@ def getSigFromStack(mptr: io.BytesIO):
74
80
r_size = int .from_bytes (mptr .read (1 ))
75
81
if r_size == 0x21 :
76
82
mptr .read (1 )
77
- r = mptr .read (0x20 )
83
+ r = mptr .read (r_size )
78
84
s_type = int .from_bytes (mptr .read (1 )) # this is always 2 and signifies int type
79
85
s_size = int .from_bytes (mptr .read (1 ))
80
86
if s_size == 0x21 :
81
87
mptr .read (1 )
82
- s = mptr .read (0x20 )
88
+ s = mptr .read (s_size )
83
89
sighash_type = mptr .read (1 )
84
90
sig = r + s + sighash_type
85
91
return sig
86
92
87
93
def op_pushdata (mptr : io .BytesIO , code : int , stack : list ):
88
94
if code <= 0x4b : # push data
89
95
size = code
90
- stack .append (mptr .read (size ))
91
96
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' )
94
98
elif code == OP_PUSHDATA2 : # OP_PUSHDATA2
95
99
size = int .from_bytes (mptr .read (2 ), byteorder = 'big' )
96
- stack .append (mptr .read (size ))
97
100
elif code == OP_PUSHDATA4 : # OP_PUSHDATA4
98
101
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 )
100
105
101
106
def hash256 (bstr ):
102
107
return hashlib .sha256 (hashlib .sha256 (bstr ).digest ()).digest ()
@@ -131,17 +136,21 @@ def splitSig(complete_sig: bytes):
131
136
r_len = int (binascii .hexlify (sigfp .read (1 )), 16 )
132
137
print ('r_len = %d' % r_len )
133
138
r = sigfp .read (r_len )
134
- print ('r = %s' % bytes .decode (binascii .hexlify (r )))
135
139
if r_len == 33 :
136
140
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 )))
137
144
int_type = sigfp .read (1 )
138
145
print ('s int_type = %d' % int (binascii .hexlify (int_type ), 16 ))
139
146
s_len = int (binascii .hexlify (sigfp .read (1 )), 16 )
140
147
print ('s_len = %d' % s_len )
141
148
s = sigfp .read (s_len )
142
- print ('s = %s' % bytes .decode (binascii .hexlify (s )))
143
149
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 )))
145
154
sighash_type = int (binascii .hexlify (sigfp .read (1 )), 16 )
146
155
print ('sighash_type = %x' % sighash_type )
147
156
return (r , s , sighash_type )
@@ -165,7 +174,7 @@ def sigcheck(sig_b: bytes, pubkey_b: bytes, raw_txn_b: bytes):
165
174
print ('invalid' )
166
175
return 0
167
176
168
- def getTxnSigned (txn : bytes , sighash_type : int ):
177
+ def getTxnSigned (txn : bytes , sighash_type : int , input_index : int ):
169
178
txn_signed_b = None
170
179
if sighash_type == g_script_sig_dict ['SIGHASH_ALL' ]:
171
180
txn_signed_b = txn ['version' ]
@@ -175,8 +184,11 @@ def getTxnSigned(txn: bytes, sighash_type: int):
175
184
for index in range (getCount (txn ['input_count' ])):
176
185
txn_signed_b += txn ['input' ][index ]['prev_txn_hash' ]
177
186
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 '
180
192
txn_signed_b += txn ['input' ][index ]['sequence' ]
181
193
txn_signed_b += txn ['out_count' ]
182
194
for index in range (getCount (txn ['out_count' ])):
@@ -494,7 +506,7 @@ def scriptParser(txn: dict, input_index: int):
494
506
pubkey_b = stack .pop ()
495
507
complete_sig_b = stack .pop ()
496
508
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 )
498
510
sig_b = r + s
499
511
is_valid = sigcheck (sig_b , pubkey_b , txn_signed_b )
500
512
stack .append (is_valid )
@@ -503,7 +515,7 @@ def scriptParser(txn: dict, input_index: int):
503
515
pubkey_b = stack .pop ()
504
516
sig_b = stack .pop () # this is R, S and sig_type
505
517
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 )
507
519
sig_b = r + s
508
520
is_valid = sigcheck (sig_b , pubkey_b , txn_signed_b )
509
521
if is_valid == 0 :
@@ -526,7 +538,7 @@ def scriptParser(txn: dict, input_index: int):
526
538
for pubkey_b in pubkey_array :
527
539
sig_b = sig_array [sig_index ]
528
540
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 )
530
542
sig_b = r + s
531
543
is_valid_sig = sigcheck (sig_b , pubkey_b , signed_txn )
532
544
if is_valid_sig == 1 :
@@ -554,7 +566,7 @@ def scriptParser(txn: dict, input_index: int):
554
566
for pubkey_b in pubkey_array :
555
567
sig_b = sig_array [sig_index ]
556
568
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 )
558
570
sig_b = r + s
559
571
is_valid_sig = sigcheck (sig_b , pubkey_b , signed_txn )
560
572
if is_valid_sig == 1 :
@@ -634,10 +646,12 @@ def get_prev_txn_info(prev_txn_hash_bigendian: str, prev_txn_out_index: int):
634
646
635
647
# skip all but required out
636
648
for index in range (out_count ):
649
+ print ('prev_txn_out_index = %d, out_count = %d' % (prev_txn_out_index , out_count ))
637
650
if index != prev_txn_out_index :
638
651
skip_satoshi = txnfp .read (8 )
639
652
skip_script_size = int (binascii .hexlify (txnfp .read (1 )), 16 )
640
653
skip_script = txnfp .read (skip_script_size )
654
+ continue
641
655
satoshis = int (binascii .hexlify (txnfp .read (8 )[::- 1 ]), 16 )
642
656
lock_script_size_b = getCountBytes (txnfp )
643
657
lock_script_size = getCount (lock_script_size_b )
@@ -714,6 +728,40 @@ def unlockTxn(mptr: mmap):
714
728
715
729
g_block_header_size = 80
716
730
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
+
717
765
if __name__ == '__main__' :
718
766
txn_hash_bigendian = binascii .unhexlify (txn_hash )[::- 1 ]
719
767
block_file_number , block_offset , txn_offset = ldb .getTxnOffset (txn_hash_bigendian )
@@ -733,3 +781,6 @@ def unlockTxn(mptr: mmap):
733
781
print ('Invalid Transaction' )
734
782
else :
735
783
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