-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
59d0b09
commit f6e547f
Showing
2 changed files
with
95 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
# objective: process transactions, validate them, mine them to a block | ||
# input: ./mempool | ||
# output: output.txt | ||
|
||
# difficulty target: 0000ffff00000000000000000000000000000000000000000000000000000000 | ||
|
||
# output format: | ||
# block header | ||
# serialized coinbase transaction | ||
# txids of the transactions mined in the block | ||
|
||
import json | ||
import os | ||
import hashlib | ||
|
||
from ecdsa import VerifyingKey, SECP256k1, BadSignatureError | ||
from ecdsa.util import sigdecode_der | ||
|
||
def serialize_transaction(transaction): | ||
prevout = transaction['vin'][0]['prevout'] | ||
scriptpubkey_type = prevout['scriptpubkey_type'] | ||
|
||
if scriptpubkey_type == 'v0_p2wpkh': | ||
serialized_tx = f"{prevout['value']}{prevout['scriptpubkey']}" | ||
else: | ||
serialized_tx = json.dumps(transaction, sort_keys=True) | ||
|
||
return serialized_tx | ||
|
||
def double_hash256(data): | ||
return hashlib.sha256(hashlib.sha256(data.encode()).digest()).digest() | ||
|
||
def load_transactions(mempool_dir): | ||
transactions = [] | ||
for filename in os.listdir(mempool_dir): | ||
if filename.endswith('.json'): | ||
with open(os.path.join(mempool_dir, filename), 'r') as file: | ||
try: | ||
transaction = json.load(file) | ||
if validate_transaction(transaction): | ||
transactions.append(transaction) | ||
except json.JSONDecodeError: | ||
continue | ||
return transactions | ||
|
||
def validate_transaction(transaction): | ||
try: | ||
txid = transaction['vin'][0]['txid'] | ||
signature_hex = transaction['vin'][0]['witness'][0] | ||
public_key_hex = transaction['vin'][0]['witness'][1] | ||
|
||
sighash_type = signature_hex[-2:] | ||
signature_bytes = bytes.fromhex(signature_hex[:-2]) | ||
|
||
serialized_tx = serialize_transaction(transaction) | ||
serialized_tx += sighash_type | ||
|
||
message_hash = double_hash256(serialized_tx) | ||
|
||
vk = VerifyingKey.from_string(bytes.fromhex(public_key_hex), curve=SECP256k1) | ||
return vk.verify(signature_bytes, message_hash, sigdecode=sigdecode_der) | ||
except (KeyError, ValueError, BadSignatureError): | ||
return False | ||
|
||
def mine_block(transactions, difficulty_target): | ||
block_data = "".join(tx['id'] for tx in transactions) | ||
nonce = 0 | ||
while True: | ||
block_header = f'{block_data}{nonce}' | ||
block_hash = hashlib.sha256(block_header.encode()).hexdigest() | ||
if block_hash < difficulty_target: | ||
break | ||
nonce += 1 | ||
return nonce, block_hash | ||
|
||
def write_output(block_hash, transactions): | ||
with open("output.txt", "w") as f: | ||
f.write(f"Block Hash: {block_hash}\n") | ||
f.write("Serialized Coinbase Transaction\n") | ||
for tx in transactions: | ||
f.write(f"{tx['id']}\n") | ||
|
||
def main(): | ||
mempool_dir = "mempool" | ||
transactions = load_transactions(mempool_dir) | ||
difficulty_target = "0000ffff00000000000000000000000000000000000000000000000000000000" | ||
_, block_hash = mine_block(transactions, difficulty_target) | ||
write_output(block_hash, transactions) | ||
|
||
if __name__ == "__main__": | ||
main() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
# Update this file to run your own code | ||
# Update this file to run your own code | ||
pip install ecdsa | ||
python main.py |