From a1f079241ecff5e8ccf7c1e4d35f565fe3e67feb Mon Sep 17 00:00:00 2001 From: davidchocholaty Date: Wed, 6 Nov 2024 22:50:47 +0100 Subject: [PATCH] Update coinbase --- src/coinbase_transaction.py | 71 ++++++++------- src/transaction.py | 175 +----------------------------------- 2 files changed, 43 insertions(+), 203 deletions(-) diff --git a/src/coinbase_transaction.py b/src/coinbase_transaction.py index af2a18c..95c13dc 100644 --- a/src/coinbase_transaction.py +++ b/src/coinbase_transaction.py @@ -1,31 +1,40 @@ -COINBASE_TRANSACTION = { - "version": 2, - "locktime": 0xffffffff, - "vin": [ - { - "txid": "0000000000000000000000000000000000000000000000000000000000000000", - "vout": 0xffffffff, - "sequence": 0xffffffff, - "is_coinbase": True, - "scriptsig": "160014fd91039e25b0827748473fce351afd8ead4ecdce", - "scriptsig_asm": "OP_PUSHBYTES_22 0014fd91039e25b0827748473fce351afd8ead4ecdce", - "witness": [ - "0000000000000000000000000000000000000000000000000000000000000000", - ] - } - ], - "vout": [ - { - "scriptpubkey": "0014ad4cc1cc859c57477bf90d0f944360d90a3998bf", - "scriptpubkey_asm": "OP_0 OP_PUSHBYTES_20 ad4cc1cc859c57477bf90d0f944360d90a3998bf", - "scriptpubkey_type": "v0_p2wpkh", - "scriptpubkey_address": "bc1q44xvrny9n3t5w7lep58egsmqmy9rnx9lt6u0tc", - "value": 100000 - }, - { - "scriptpubkey": "", - "scriptpubkey_type": "op_return", - "value": 0 - } - ] - } \ No newline at end of file +COINBASE_TRANSACTION = { + "version": 1, + "locktime": 0, + "vin": [ + { + "txid": "0000000000000000000000000000000000000000000000000000000000000000", + "vout": 4294967295, + "prevout": { + "scriptpubkey": "41047eda6bd04fb27cab6e7c28c99b94977f073e912f25d1ff7165d9c95cd9bbe6da7e7ad7f2acb09e0ced91705f7616af53bee51a238b7dc527f2be0aa60469d140ac", + "scriptpubkey_asm": "OP_HASH160 OP_PUSHBYTES_20 423877331b30a905240c7e1f2adee4ebaa47c5f6 OP_EQUAL", + "scriptpubkey_type": "p2sh", + "scriptpubkey_address": "14gnf7L2DjBYKFuWb6iftBoWE9hmAoFbcF", + "value": 2504928, + }, + "scriptsig": "03233708184d696e656420627920416e74506f6f6c373946205b8160a4256c0000946e0100", + "scriptsig_asm": "OP_PUSHBYTES_22 001415ff0337937ecadd10ce56ffdfd4674817613223", + "witness": [ + "0000000000000000000000000000000000000000000000000000000000000000", + ], + "is_coinbase": True, + "sequence": 4294967295, + } + ], + "vout": [ + { + "scriptpubkey": "76a914edf10a7fac6b32e24daa5305c723f3de58db1bc888ac", + "scriptpubkey_asm": "OP_DUP OP_HASH160 OP_PUSHBYTES_20 71a3d2f54b0917dc9d2c877b2861ac52967dec7f OP_EQUALVERIFY OP_CHECKSIG", + "scriptpubkey_type": "p2pkh", + "scriptpubkey_address": "1BMscNZbFKdUDYi3bnF5XEmkWT3WPmRBDJ", + "value": 28278016, + }, + { + "scriptpubkey": "", + "scriptpubkey_asm": "OP_HASH160 OP_PUSHBYTES_20 423877331b30a905240c7e1f2adee4ebaa47c5f6 OP_EQUAL", + "scriptpubkey_type": "p2sh", + "scriptpubkey_address": "37jAAWEdJ9D9mXybRobcveioxSkt7Lkwog", + "value": 0000000000000000, + }, + ], + } diff --git a/src/transaction.py b/src/transaction.py index ce0ba23..45d13ba 100644 --- a/src/transaction.py +++ b/src/transaction.py @@ -105,16 +105,12 @@ def valid_input(self, vin_idx, vin): return self.validate_p2pkh(vin_idx, vin) elif scriptpubkey_type == "p2sh": pass - #return self.validate_p2sh_p2wpkh(vin_idx, vin) elif scriptpubkey_type == "v0_p2wsh": pass - #return self.validate_p2wsh(vin) elif scriptpubkey_type == "v1_p2tr": pass - #return self.validate_p2tr(vin) elif scriptpubkey_type == "v0_p2wpkh": - pass - #return self.validate_p2wpkh(vin) + return self.validate_p2wpkh(vin) # Unknown script type. return False @@ -142,171 +138,6 @@ def validate_p2pkh(self, vin_idx, vin): #print(is_valid) return is_valid -""" - ##################################################################### - # Extract signature and public key from scriptSig (Parse scriptSig) # - ##################################################################### - # https://learnmeabitcoin.com/technical/script/p2pkh/ - # Explanation: the scriptSig contains the signature and the public key (including ASM instructions). - - signature_len = scriptsig[0] # The first byte represents the length of the DER signature (including hash type) - signature_w_hash_type = scriptsig[1:1+signature_len] # Extract the signature (includes the hash type at the end) - - # The last byte of the signature is the hash type (e.g., SIGHASH_ALL = 0x01) - signature = signature_w_hash_type[:-1] - hash_type = signature_w_hash_type[-1] - - public_key_idx = 1 + signature_len - public_key_len = scriptsig[public_key_idx] - public_key = scriptsig[public_key_idx+1:public_key_idx+1+public_key_len] - - ####################### - # Parse DER signature # - ####################### - # https://bitcoin.stackexchange.com/questions/92680/what-are-the-der-signature-and-sec-format - # https://learnmeabitcoin.com/technical/keys/signature/ - - # Remove the hash_type from the DER signature - der_signature = signature_w_hash_type[:-1] - - r, s, hash_type = parse_der_signature_bytes(der_signature) - - der_len = len(der_signature) - signature_len = len(r + s) + 6 - - if der_len != signature_len: - return False - - signature = r + s - #print(signature) - - ###################### - # Parse scriptPubKey # - ###################### - # https://learnmeabitcoin.com/technical/script/p2pkh/ - # Explanation: the scriptPubKey contains: DUP, HASH160, public key hash (including OP_PUSHBYTES_20), EQUALVERIFY and CHECKSIG. - - if scriptpubkey[0:1] != b'\x76' or scriptpubkey[1:2] != b'\xa9' or scriptpubkey[2:3] != b'\x14': - return False # Not a valid P2PKH scriptPubKey (missing OP_DUP, OP_HASH160, or length mismatch) - - if scriptpubkey[23:24] != b'\x88' or scriptpubkey[24:25] != b'\xac': - return False # Not a valid P2PKH scriptPubKey (missing OP_EQUALVERIFY or OP_CHECKSIG) - - pkh = scriptpubkey[3:23] - - # Compute the public key hash (HASH160 of the public key) and compare with scriptPubKey - calc_pkh = hash160(public_key) - if calc_pkh != pkh: - return False # Public key hash does not match - - ############################################ - # Verify the signature with the public key # - ############################################ - - data_signed = serialize_transaction(self.json_transaction, vin_idx, int(hash_type)) - data_hash = hashlib.sha256(data_signed).digest() - - #print(self.json_transaction) - #print("********************************") - - # Verify the signature - verifying_key = VerifyingKey.from_string(public_key, curve=SECP256k1) - try: - verifying_key.verify(signature, data_hash, hashlib.sha256) - except BadSignatureError: - return False - - print(public_key) - print("-------------------") - return True -""" -""" - def validate_p2sh_p2wpkh(self, vin_idx, vin): - # Extract scriptSig and witness - scriptsig = decode_hex(vin.get("scriptsig", "")) - witness = vin.get("witness", []) - - if not scriptsig or len(witness) < 2: - return False - - print(vin["txid"]) - - prevout = vin.get("prevout", {}) - - if not prevout: - return False - - scriptpubkey = decode_hex(prevout.get("scriptpubkey", "")) - - ############################# - # Check if it's a P2SH script # - ############################# - if len(scriptpubkey) != 23 or scriptpubkey[0:1] != b'\xa9' or scriptpubkey[-1:] != b'\x87': - return False # Not a valid P2SH scriptPubKey - - # Extract the redeem script hash from the scriptPubKey - # Extract redeem script hash from scriptPubKey - if scriptpubkey[0] != 0xa9: # Check for OP_HASH160 - return False - - length_of_hash = scriptpubkey[1] - if length_of_hash != 0x14: # 20 bytes - return False - - expected_redeem_script_hash = scriptpubkey[2:2+length_of_hash] - - ########################### - # Extract the redeem script # - ########################### - # The redeem script is the data in the scriptSig - redeem_script = scriptsig - - # Hash the redeem script and compare it with the expected hash in the scriptPubKey - redeem_script_hash = hash160(redeem_script) - - #print("rsh: ", redeem_script_hash) - #print("ersh: ", expected_redeem_script_hash) - - if redeem_script_hash != expected_redeem_script_hash: - return False # Redeem script hash does not match - - ############################## - # Parse and execute redeem script # - ############################## - # The redeem script should be a P2WPKH script: OP_0 <20-byte-public-key-hash> - if len(redeem_script) != 22 or redeem_script[0:1] != b'\x00' or redeem_script[1:2] != b'\x14': - return False # Not a valid P2WPKH redeem script - - # Extract the public key hash from the redeem script - public_key_hash = redeem_script[2:] - - ###################### - # Verify the witness # - ###################### - # The witness field contains: - # - witness[0] = signature - # - witness[1] = public key - - signature = decode_hex(witness[0]) - public_key = decode_hex(witness[1]) - - # Compute the public key hash (HASH160 of the public key) and compare with the public key hash in the redeem script - calc_pkh = hash160(public_key) - if calc_pkh != public_key_hash: - return False # Public key hash does not match - - ############################################ - # Verify the signature with the public key # - ############################################ - - data_signed = serialize_transaction(self.json_transaction, vin_idx, 1) # SIGHASH_ALL is typically 1 - data_hash = hashlib.sha256(data_signed).digest() - - # Verify the signature - verifying_key = VerifyingKey.from_string(public_key, curve=SECP256k1) - try: - verifying_key.verify(signature[:-1], data_hash, hashlib.sha256) # Remove the last byte (hash type) - except BadSignatureError: - return False - return True """ + def validate_p2wpkh(self, vin): + return False