I am trying to understand and verify P2SH script by writing a python code to parse real transaction in blockchain. I have chosen below Transaction randomly. TxID: 7edb32d4ffd7a385b763c7a8e56b6358bcd729e747290624e18acdbe6209fc45
I am getting BadSignatureError.
Raw transaction:
bitcoin-cli getrawtransaction 7edb32d4ffd7a385b763c7a8e56b6358bcd729e747290624e18acdbe6209fc45
0100000001c8cc2b56525e734ff63a13bc6ad06a9e5664df8c67632253a8e36017aee3ee40000000009000483045022100ad0851c69dd756b45190b5a8e97cb4ac3c2b0fa2f2aae23aed6ca97ab33bf88302200b248593abc1259512793e7dea61036c601775ebb23640a0120b0dba2c34b79001455141042f90074d7a5bf30c72cf3a8dfd1381bdbd30407010e878f3a11269d5f74a58788505cdca22ea6eab7cfb40dc0e07aba200424ab0d79122a653ad0c7ec9896bdf51aefeffffff0120f40e00000000001976a9141d30342095961d951d306845ef98ac08474b36a088aca7270400
Decode above Raw transaction and get Transaction ID of locking script:
bitcoin-cli decoderawtransaction $(bitcoin-cli getrawtransaction 7edb32d4ffd7a385b763c7a8e56b6358bcd729e747290624e18acdbe6209fc45)
{
"txid": "7edb32d4ffd7a385b763c7a8e56b6358bcd729e747290624e18acdbe6209fc45",
"hash": "7edb32d4ffd7a385b763c7a8e56b6358bcd729e747290624e18acdbe6209fc45",
"version": 1,
"size": 229,
"vsize": 229,
"weight": 916,
"locktime": 272295,
"vin": [
{
"txid": "40eee3ae1760e3a8532263678cdf64569e6ad06abc133af64f735e52562bccc8",
"vout": 0,
"scriptSig": {
"asm": "0 3045022100ad0851c69dd756b45190b5a8e97cb4ac3c2b0fa2f2aae23aed6ca97ab33bf88302200b248593abc1259512793e7dea61036c601775ebb23640a0120b0dba2c34b790[ALL] 5141042f90074d7a5bf30c72cf3a8dfd1381bdbd30407010e878f3a11269d5f74a58788505cdca22ea6eab7cfb40dc0e07aba200424ab0d79122a653ad0c7ec9896bdf51ae",
"hex": "00483045022100ad0851c69dd756b45190b5a8e97cb4ac3c2b0fa2f2aae23aed6ca97ab33bf88302200b248593abc1259512793e7dea61036c601775ebb23640a0120b0dba2c34b79001455141042f90074d7a5bf30c72cf3a8dfd1381bdbd30407010e878f3a11269d5f74a58788505cdca22ea6eab7cfb40dc0e07aba200424ab0d79122a653ad0c7ec9896bdf51ae"
},
"sequence": 4294967294
}
],
"vout": [
{
"value": 0.00980000,
"n": 0,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 1d30342095961d951d306845ef98ac08474b36a0 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a9141d30342095961d951d306845ef98ac08474b36a088ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"13fLLox43yXYvfoZadXpGbkTUXkW8bhqut"
]
}
}
]
}
Get Decoded Transaction of locking script:
bitcoin-cli decoderawtransaction $(bitcoin-cli getrawtransaction 40eee3ae1760e3a8532263678cdf64569e6ad06abc133af64f735e52562bccc8)
{
"txid": "40eee3ae1760e3a8532263678cdf64569e6ad06abc133af64f735e52562bccc8",
"hash": "40eee3ae1760e3a8532263678cdf64569e6ad06abc133af64f735e52562bccc8",
"version": 1,
"size": 189,
"vsize": 189,
"weight": 756,
"locktime": 0,
"vin": [
{
"txid": "42a3fdd7d7baea12221f259f38549930b47cec288b55e4a8facc3c899f4775da",
"vout": 0,
"scriptSig": {
"asm": "3044022048d1468895910edafe53d4ec4209192cc3a8f0f21e7b9811f83b5e419bfb57e002203fef249b56682dbbb1528d4338969abb14583858488a3a766f609185efe68bca[ALL] 031a455dab5e1f614e574a2f4f12f22990717e93899695fb0d81e4ac2dcfd25d00",
"hex": "473044022048d1468895910edafe53d4ec4209192cc3a8f0f21e7b9811f83b5e419bfb57e002203fef249b56682dbbb1528d4338969abb14583858488a3a766f609185efe68bca0121031a455dab5e1f614e574a2f4f12f22990717e93899695fb0d81e4ac2dcfd25d00"
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.00990000,
"n": 0,
"scriptPubKey": {
"asm": "OP_HASH160 e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a OP_EQUAL",
"hex": "a914e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a87",
"reqSigs": 1,
"type": "scripthash",
"addresses": [
"3P14159f73E4gFr7JterCCQh9QjiTjiZrG"
]
}
}
]
}
We need to evaluate unlocking script + locking script.
unlocking script:
00483045022100ad0851c69dd756b45190b5a8e97cb4ac3c2b0fa2f2aae23aed6ca97ab33bf88302200b248593abc1259512793e7dea61036c601775ebb23640a0120b0dba2c34b79001455141042f90074d7a5bf30c72cf3a8dfd1381bdbd30407010e878f3a11269d5f74a58788505cdca22ea6eab7cfb40dc0e07aba200424ab0d79122a653ad0c7ec9896bdf51ae
Evaluate unlocking script:
step 1: stack -> 0x00 (OP_0)
step 2: stack -> 0x00, 0x3045022100ad0851c69dd756b45190b5a8e97cb4ac3c2b0fa2f2aae23aed6ca97ab33bf88302200b248593abc1259512793e7dea61036c601775ebb23640a0120b0dba2c34b79001
step 3: stack -> 0x00,
0x3045022100ad0851c69dd756b45190b5a8e97cb4ac3c2b0fa2f2aae23aed6ca97ab33bf88302200b248593abc1259512793e7dea61036c601775ebb23640a0120b0dba2c34b79001,
0x5141042f90074d7a5bf30c72cf3a8dfd1381bdbd30407010e878f3a11269d5f74a58788505cdca22ea6eab7cfb40dc0e07aba200424ab0d79122a653ad0c7ec9896bdf51ae
Copy this stack as stack_copy
locking script:
a914e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a87
Evaluate locking script now with the stack:
step 4: 0xa9 (OP_HASH160)
stack -> 0x00,
0x3045022100ad0851c69dd756b45190b5a8e97cb4ac3c2b0fa2f2aae23aed6ca97ab33bf88302200b248593abc1259512793e7dea61036c601775ebb23640a0120b0dba2c34b79001,
0xe9c3dd0c07aac76179ebc76a6c78d4d67c6c160a
step 5: 0x14 (pushdata 20 bytes) 0xe9c3dd0c07aac76179ebc76a6c78d4d67c6c160a
stack -> 0x00,
0x3045022100ad0851c69dd756b45190b5a8e97cb4ac3c2b0fa2f2aae23aed6ca97ab33bf88302200b248593abc1259512793e7dea61036c601775ebb23640a0120b0dba2c34b79001,
0xe9c3dd0c07aac76179ebc76a6c78d4d67c6c160a,
0xe9c3dd0c07aac76179ebc76a6c78d4d67c6c160a
step 6: 87 OP_EQUAL
stack -> 0x00,
0x3045022100ad0851c69dd756b45190b5a8e97cb4ac3c2b0fa2f2aae23aed6ca97ab33bf88302200b248593abc1259512793e7dea61036c601775ebb23640a0120b0dba2c34b79001,
0x01
Since OP_EQUAL returned True and it is P2SH we evaluate redeem script against copied stack
stack = stack_copy
redeem script = stack.pop():
0x5141042f90074d7a5bf30c72cf3a8dfd1381bdbd30407010e878f3a11269d5f74a58788505cdca22ea6eab7cfb40dc0e07aba200424ab0d79122a653ad0c7ec9896bdf51ae
Evaluate redeem script:
step 7: 0x51 (OP_1)
stack -> 0x00,
0x3045022100ad0851c69dd756b45190b5a8e97cb4ac3c2b0fa2f2aae23aed6ca97ab33bf88302200b248593abc1259512793e7dea61036c601775ebb23640a0120b0dba2c34b79001,
0x01
step 8: 0x41 (Pushdata 65 bytes) 042f90074d7a5bf30c72cf3a8dfd1381bdbd30407010e878f3a11269d5f74a58788505cdca22ea6eab7cfb40dc0e07aba200424ab0d79122a653ad0c7ec9896bdf
stack -> 0x00,
0x3045022100ad0851c69dd756b45190b5a8e97cb4ac3c2b0fa2f2aae23aed6ca97ab33bf88302200b248593abc1259512793e7dea61036c601775ebb23640a0120b0dba2c34b79001,
0x01,
0x042f90074d7a5bf30c72cf3a8dfd1381bdbd30407010e878f3a11269d5f74a58788505cdca22ea6eab7cfb40dc0e07aba200424ab0d79122a653ad0c7ec9896bdf
step 9: 0x51 (OP_1)
stack -> 0x00,
0x3045022100ad0851c69dd756b45190b5a8e97cb4ac3c2b0fa2f2aae23aed6ca97ab33bf88302200b248593abc1259512793e7dea61036c601775ebb23640a0120b0dba2c34b79001,
0x01,
0x042f90074d7a5bf30c72cf3a8dfd1381bdbd30407010e878f3a11269d5f74a58788505cdca22ea6eab7cfb40dc0e07aba200424ab0d79122a653ad0c7ec9896bdf,
0x01
step 10: 0xae (OP_CHECKMULTISIG)
We have 1 sig and 1 pubkey. To check multisig we need to get transaction which was signed. We will come back to this step once we have transaction which was signed.
Signature from stack:
0x3045022100ad0851c69dd756b45190b5a8e97cb4ac3c2b0fa2f2aae23aed6ca97ab33bf88302200b248593abc1259512793e7dea61036c601775ebb23640a0120b0dba2c34b79001
Parse Signature:
0x30 DER
0x45 Length
0x02 Type Integer
0x21 Length of r
00 (ignore) ad0851c69dd756b45190b5a8e97cb4ac3c2b0fa2f2aae23aed6ca97ab33bf883 (r)
02 Type Integer
20 Length of s
0b248593abc1259512793e7dea61036c601775ebb23640a0120b0dba2c34b790 (s)
01 SIGHASH_ALL
Sig-type is SIGHASH_ALL so we replace only unlocking script with locking script.
r||s: -------------------------------------------------------------(1) ad0851c69dd756b45190b5a8e97cb4ac3c2b0fa2f2aae23aed6ca97ab33bf8830b248593abc1259512793e7dea61036c601775ebb23640a0120b0dba2c34b790
Parsing raw transaction of unlocking script:
01 00 00 00 Version
01 input count
c8 cc 2b 56 52 5e 73 4f f6 3a 13 bc 6a d0 6a 9e 56 64 df 8c 67 63 22 53 a8 e3 60 17 ae e3 ee 40 Previous transaction
00 00 00 00 Previous transaction out index
--------- replace this [
90
00 48 30 45 02 21 00 ad 08 51 c6 9d d7 56 b4 51
90 b5 a8 e9 7c b4 ac 3c 2b 0f a2 f2 aa e2 3a ed
6c a9 7a b3 3b f8 83 02 20 0b 24 85 93 ab c1 25
95 12 79 3e 7d ea 61 03 6c 60 17 75 eb b2 36 40
a0 12 0b 0d ba 2c 34 b7 90 01 45 51 41 04 2f 90
07 4d 7a 5b f3 0c 72 cf 3a 8d fd 13 81 bd bd 30
40 70 10 e8 78 f3 a1 12 69 d5 f7 4a 58 78 85 05
cd ca 22 ea 6e ab 7c fb 40 dc 0e 07 ab a2 00 42
4a b0 d7 91 22 a6 53 ad 0c 7e c9 89 6b df 51 ae
------------- ]
fe ff ff ff sequence
01 out count
20 f4 0e 00 00 00 00 00 value
19 script size
76 a9 14 1d 30 34 20 95 96 1d 95 1d 30 68 45 ef 98 ac 08 47 4b 36 a0 88 ac script pubkey
a7 27 04 00 lock time
---> Add SIGHASH_ALL here
After replacing locking script with unlocking script:
01 00 00 00 Version
01 input count
c8 cc 2b 56 52 5e 73 4f f6 3a 13 bc 6a d0 6a 9e 56 64 df 8c 67 63 22 53 a8 e3 60 17 ae e3 ee 40 Previous transaction
00 00 00 00 Previous transaction out index
------- locking script [
17
a914e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a87
------- ]
fe ff ff ff sequence
01 out count
20 f4 0e 00 00 00 00 00 value
19 script size
76 a9 14 1d 30 34 20 95 96 1d 95 1d 30 68 45 ef 98 ac 08 47 4b 36 a0 88 ac
a7 27 04 00 lock time
01 00 00 00 SIGHASH_ALL
Now performing OP_CHECKMULTISIG: So we have transaction which is signed: ------------------------------(2)
0100000001c8cc2b56525e734ff63a13bc6ad06a9e5664df8c67632253a8e36017aee3ee400000000017a914e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a87feffffff0120f40e00000000001976a9141d30342095961d951d306845ef98ac08474b36a088aca727040001000000
On stack we have: 0x00 -> Signature -> 0x01 -> Pubkey -> 0x01
pubkey : 0x042f90074d7a5bf30c72cf3a8dfd1381bdbd30407010e878f3a11269d5f74a58788505cdca22ea6eab7cfb40dc0e07aba200424ab0d79122a653ad0c7ec9896bdf
0x04 denote uncompressed. Removing that we have: Pubkey : --------------------------------------------------------------(3)
0x2f90074d7a5bf30c72cf3a8dfd1381bdbd30407010e878f3a11269d5f74a58788505cdca22ea6eab7cfb40dc0e07aba200424ab0d79122a653ad0c7ec9896bdf
I used r||s as bytes of (1), raw_txn as bytes of (2) and pub_key as bytes as (3) for argument of below Python code to perform sigcheck:
def sigcheck(sig_b: bytes, pubkey_b: bytes, raw_txn_b: bytes):
txn_sha256_b = hashlib.sha256(raw_txn_b).digest()
prefix = pubkey_b[0:1]
print('prefix = %s' % prefix)
print('input pubkey = %s' % bytes.decode(binascii.hexlify(pubkey_b)))
if prefix == b'\x02' or prefix == b'\x03':
pubkey_b = getFullPubKeyFromCompressed(pubkey_b)[1:]
elif prefix == b'\x04':
pubkey_b = pubkey_b[1:]
try:
print("full public key = %s" % bytes.decode(binascii.hexlify(pubkey_b)))
vk = ecdsa.VerifyingKey.from_string(pubkey_b, curve=ecdsa.SECP256k1)
if vk.verify(sig_b, txn_sha256_b, hashlib.sha256) == True:
print('valid')
return 1
else:
print('sigcheck: invalid')
return 0
except ecdsa.BadSignatureError:
print('sigcheck: Bad Signature')
return 0
This program works perfectly to checksig in P2PKH scenario but it is failing here and I have no clue. Running this program I am getting BadSignatureError.
I have given in great detail what I am doing. Please help me understand and solve this.