From 421c6f8343e64645d6eed3192b14f2e9303f52f2 Mon Sep 17 00:00:00 2001 From: davidchocholaty Date: Thu, 7 Nov 2024 16:18:38 +0100 Subject: [PATCH] Add p2sh --- src/script.py | 2 +- src/transaction.py | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/script.py b/src/script.py index b62cc79..683a34c 100644 --- a/src/script.py +++ b/src/script.py @@ -430,7 +430,7 @@ def op_checkmultisig(self) -> int: # 3. Handle proper error cases verified = True # Replace with actual verification - + self.stack.push(b'\x01' if verified else b'\x00') return 1 diff --git a/src/transaction.py b/src/transaction.py index 661fedd..5a4ad3e 100644 --- a/src/transaction.py +++ b/src/transaction.py @@ -104,7 +104,7 @@ def valid_input(self, vin_idx, vin): if scriptpubkey_type == "p2pkh": return self.validate_p2pkh(vin_idx, vin) elif scriptpubkey_type == "p2sh": - pass + return self.validate_p2sh(vin_idx, vin) elif scriptpubkey_type == "v0_p2wsh": pass elif scriptpubkey_type == "v1_p2tr": @@ -139,6 +139,47 @@ def validate_p2pkh(self, vin_idx, vin): return is_valid + def validate_p2sh(self, vin_idx, vin): + ################# + # Pubkey script # + ################# + scriptsig = decode_hex(vin.get("scriptsig", "")) + if not scriptsig: + return False + prevout = vin.get("prevout", {}) + if not prevout: + return False + scriptpubkey = decode_hex(prevout.get("scriptpubkey", "")) + + # Check if the scriptpubkey is a P2SH script + if scriptpubkey[:2] != b'\xa9\x14' or scriptpubkey[-1:] != b'\x87': + # Not a P2SH script, fallback to P2PKH validation + return self.validate_p2pkh(vin_idx, vin) + + # Extract the script hash from the scriptpubkey + script_hash = scriptpubkey[2:-1] + + # Find the redeem script in the scriptsig + redeem_script_len = int.from_bytes(scriptsig[0:1], byteorder='little') + redeem_script = scriptsig[1:1+redeem_script_len] + + # Create the combined script + script = Script.combine_scripts(redeem_script, json_transaction=self.json_transaction) + + # Hash the redeem script and compare with the script hash + # Compute the HASH160 (RIPEMD-160 of SHA-256) of the redeem script + sha256_hash = hashlib.sha256(redeem_script).digest() + computed_script_hash = hashlib.new('ripemd160', sha256_hash).digest() + + # Compare with the provided script hash + if computed_script_hash != script_hash: + return False + + # Execute the redeem script + is_valid = script.execute() + + return is_valid + def validate_p2wpkh(self, vin_idx, vin): """ Validate a Pay-to-Witness-Public-Key-Hash (P2WPKH) transaction input @@ -200,6 +241,7 @@ def validate_p2wpkh(self, vin_idx, vin): # Execute the script try: + #return script.execute() return script.execute() except Exception as e: print(f"P2WPKH validation error: {str(e)}")