Skip to content

Commit

Permalink
Update coinbase
Browse files Browse the repository at this point in the history
  • Loading branch information
davidchocholaty committed Nov 6, 2024
1 parent 8c80537 commit a1f0792
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 203 deletions.
71 changes: 40 additions & 31 deletions src/coinbase_transaction.py
Original file line number Diff line number Diff line change
@@ -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
}
]
}
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,
},
],
}
175 changes: 3 additions & 172 deletions src/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

0 comments on commit a1f0792

Please sign in to comment.