Next scheduled rescrape ... never
Version 1
Last scraped
Edited on 12/08/2025, 13:34:04 UTC
This Python script generates a fully signed raw Bitcoin transaction that can be used with the MARA Slipstream service (or any other broadcast method).

Automatically:
Fetches UTXOs (unspent outputs) from mempool.space

Code:
import base58
import requests
import ecdsa
from bitcoin import *
import hashlib

def decode_wif(wif):
    b = base58.b58decode(wif)
    if len(b) == 38 and b[-5] == 0x01:
        return b[1:-5], True  # compressed
    elif len(b) == 37:
        return b[1:-1], False  # uncompressed
    raise ValueError("Invalid WIF format")

def get_pubkey(priv_bytes, compressed=True):
    sk = ecdsa.SigningKey.from_string(priv_bytes, curve=ecdsa.SECP256k1)
    vk = sk.get_verifying_key()
    x = vk.pubkey.point.x()
    y = vk.pubkey.point.y()
    return ('02' if y % 2 == 0 else '03') + f"{x:064x}"  # Always compressed

def get_address(pubkey):
    pubkey_bytes = bytes.fromhex(pubkey)
    pubkey_hash = hash160(pubkey_bytes)
    return pubkey_to_address(pubkey)  # Always compressed P2PKH

def is_legacy_address(address):
    return address.startswith('1')

def fetch_utxos(address):
    if not is_legacy_address(address):
        raise ValueError("Only legacy addresses (starting with '1') are supported")
    
    try:
        url = f"https://mempool.space/api/address/{address}/utxo"
        r = requests.get(url)
        r.raise_for_status()
        return r.json()
    except Exception as e:
        print("Failed to fetch UTXOs:", e)
        return []

def estimate_fee(num_inputs, num_outputs, fee_rate):
    # Legacy transaction size estimation with compressed pubkeys
    input_size = 148  # Standard for P2PKH with compressed pubkey
    output_size = 34   # P2PKH output size
    total_size = 10 + num_inputs * input_size + num_outputs * output_size
    return total_size * fee_rate

def create_transaction(wif, to_address, amount_btc, fee_rate):
    # Validate addresses are legacy
    if not is_legacy_address(to_address):
        raise ValueError("Only legacy addresses (starting with '1') are supported for recipient")
    
    priv_bytes, _ = decode_wif(wif)  
    pubkey = get_pubkey(priv_bytes)
    from_address = get_address(pubkey)
    
    if not is_legacy_address(from_address):
        raise ValueError("Only legacy addresses (starting with '1') are supported for sender")

    utxos = fetch_utxos(from_address)
    if not utxos:
        raise RuntimeError("No UTXOs available")

    # Sort UTXOs by value (descending) to minimize number of inputs
    utxos.sort(key=lambda x: x['value'], reverse=True)

    inputs = []
    total = 0
    for utxo in utxos:
        inputs.append({'output': f"{utxo['txid']}:{utxo['vout']}", 'value': utxo['value']})
        total += utxo['value']
        if total >= int(amount_btc * 1e8) + estimate_fee(len(inputs), 2, fee_rate):
            break  # We have enough including fees

    if total == 0:
        raise RuntimeError("No UTXOs available")

    send_amount = int(amount_btc * 1e8)
    fee = estimate_fee(len(inputs), 2, fee_rate)

    if total < send_amount + fee:
        raise RuntimeError(f"Insufficient funds. Need {send_amount + fee} satoshis, have {total}")

    change = total - send_amount - fee
    outputs = [{'address': to_address, 'value': send_amount}]
    if change > 546:  # Minimum dust amount
        outputs.append({'address': from_address, 'value': change})
    elif change > 0:
        fee += change  # Add remaining change to fee if it's too small

    tx = mktx(inputs, outputs)
    for i in range(len(inputs)):
        tx = sign(tx, i, wif)
    return tx

# === Example Usage ===
if __name__ == "__main__":
    WIF = "<wif_private_key>"
    TO_ADDRESS = "1YourLegacyAddressHere"  # must start with '1'
    AMOUNT_BTC = 6.70013241
    FEE_RATE = 20  # sats/vB

    try:
        raw_tx = create_transaction(WIF, TO_ADDRESS, AMOUNT_BTC, FEE_RATE)
        print("Raw Transaction:", raw_tx)
        
        # To broadcast the transaction (uncomment to use)
        # broadcast_url = "https://mempool.space/api/tx"
        # response = requests.post(broadcast_url, data=raw_tx)
        # print("Broadcast response:", response.text)
    except Exception as e:
        print("Error:", e)

Example script output

Quote
Raw Transaction: 0100000002b3138da741af259146ca2c4895bac7e0c08147679f88ce3302fb4db0584bf31205000 0006b4830450221009131a350b98aab71d77f5a9a94dd5bac9a5602e2b761a2dc605ba03cb996df ff0220480b53128af0cf7c9b74fa8d625e2a9d143d15fdaa2fd24e421d4d0d29c1532201210279b e667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff6441384445 a0f426ee689e2532e41fc6947dda41558026b80f5b1dfd7c58455d130000006a473044022032ccf 651486b1055ea188d95645dc61329e9fa89a18b33417d33dc0aa61484d602206bbb8e8cf1b2a6e8 ea64f78f7d7625d05014f593c76438c7127d5e2b147d971601210279be667ef9dcbbac55a06295c e870b07029bfcdb2dce28d959f2815b16f81798ffffffff023997ef27000000001976a914751e76 e8199196d454941c45d1b3a323f1433bd688acafb2f501000000001976a914f6f5431d25bbf7b12 e8add9af5e3475c44a0a5b888ac00000000


Cheers Grin


Did u test it? Do you have a example that it worked out?



Cheers Grin


There's just one thing left. How do I get the WIF from puzzle 71?   Undecided

I accidentally found it when i was typing  18 random numbers, i will send you so you can be happy Grin
Original archived Re: Bitcoin puzzle transaction ~32 BTC prize to who solves it
Scraped on 05/08/2025, 13:34:42 UTC
This Python script generates a fully signed raw Bitcoin transaction that can be used with the MARA Slipstream service (or any other broadcast method).

Automatically:
Fetches UTXOs (unspent outputs) from mempool.space

Code:
import base58
import requests
import ecdsa
from bitcoin import *
import hashlib

def decode_wif(wif):
    b = base58.b58decode(wif)
    if len(b) == 38 and b[-5] == 0x01:
        return b[1:-5], True  # compressed
    elif len(b) == 37:
        return b[1:-1], False  # uncompressed
    raise ValueError("Invalid WIF format")

def get_pubkey(priv_bytes, compressed=True):
    sk = ecdsa.SigningKey.from_string(priv_bytes, curve=ecdsa.SECP256k1)
    vk = sk.get_verifying_key()
    x = vk.pubkey.point.x()
    y = vk.pubkey.point.y()
    return ('02' if y % 2 == 0 else '03') + f"{x:064x}"  # Always compressed

def get_address(pubkey):
    pubkey_bytes = bytes.fromhex(pubkey)
    pubkey_hash = hash160(pubkey_bytes)
    return pubkey_to_address(pubkey)  # Always compressed P2PKH

def is_legacy_address(address):
    return address.startswith('1')

def fetch_utxos(address):
    if not is_legacy_address(address):
        raise ValueError("Only legacy addresses (starting with '1') are supported")
    
    try:
        url = f"https://mempool.space/api/address/{address}/utxo"
        r = requests.get(url)
        r.raise_for_status()
        return r.json()
    except Exception as e:
        print("Failed to fetch UTXOs:", e)
        return []

def estimate_fee(num_inputs, num_outputs, fee_rate):
    # Legacy transaction size estimation with compressed pubkeys
    input_size = 148  # Standard for P2PKH with compressed pubkey
    output_size = 34   # P2PKH output size
    total_size = 10 + num_inputs * input_size + num_outputs * output_size
    return total_size * fee_rate

def create_transaction(wif, to_address, amount_btc, fee_rate):
    # Validate addresses are legacy
    if not is_legacy_address(to_address):
        raise ValueError("Only legacy addresses (starting with '1') are supported for recipient")
    
    priv_bytes, _ = decode_wif(wif)  
    pubkey = get_pubkey(priv_bytes)
    from_address = get_address(pubkey)
    
    if not is_legacy_address(from_address):
        raise ValueError("Only legacy addresses (starting with '1') are supported for sender")

    utxos = fetch_utxos(from_address)
    if not utxos:
        raise RuntimeError("No UTXOs available")

    # Sort UTXOs by value (descending) to minimize number of inputs
    utxos.sort(key=lambda x: x['value'], reverse=True)

    inputs = []
    total = 0
    for utxo in utxos:
        inputs.append({'output': f"{utxo['txid']}:{utxo['vout']}", 'value': utxo['value']})
        total += utxo['value']
        if total >= int(amount_btc * 1e8) + estimate_fee(len(inputs), 2, fee_rate):
            break  # We have enough including fees

    if total == 0:
        raise RuntimeError("No UTXOs available")

    send_amount = int(amount_btc * 1e8)
    fee = estimate_fee(len(inputs), 2, fee_rate)

    if total < send_amount + fee:
        raise RuntimeError(f"Insufficient funds. Need {send_amount + fee} satoshis, have {total}")

    change = total - send_amount - fee
    outputs = [{'address': to_address, 'value': send_amount}]
    if change > 546:  # Minimum dust amount
        outputs.append({'address': from_address, 'value': change})
    elif change > 0:
        fee += change  # Add remaining change to fee if it's too small

    tx = mktx(inputs, outputs)
    for i in range(len(inputs)):
        tx = sign(tx, i, wif)
    return tx

# === Example Usage ===
if __name__ == "__main__":
    WIF = "<wif_private_key>"
    TO_ADDRESS = "1YourLegacyAddressHere"  # must start with '1'
    AMOUNT_BTC = 6.70013241
    FEE_RATE = 20  # sats/vB

    try:
        raw_tx = create_transaction(WIF, TO_ADDRESS, AMOUNT_BTC, FEE_RATE)
        print("Raw Transaction:", raw_tx)
        
        # To broadcast the transaction (uncomment to use)
        # broadcast_url = "https://mempool.space/api/tx"
        # response = requests.post(broadcast_url, data=raw_tx)
        # print("Broadcast response:", response.text)
    except Exception as e:
        print("Error:", e)

Example script output

Quote
Raw Transaction: 0100000002b3138da741af259146ca2c4895bac7e0c08147679f88ce3302fb4db0584bf31205000 0006b4830450221009131a350b98aab71d77f5a9a94dd5bac9a5602e2b761a2dc605ba03cb996df ff0220480b53128af0cf7c9b74fa8d625e2a9d143d15fdaa2fd24e421d4d0d29c1532201210279b e667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff6441384445 a0f426ee689e2532e41fc6947dda41558026b80f5b1dfd7c58455d130000006a473044022032ccf 651486b1055ea188d95645dc61329e9fa89a18b33417d33dc0aa61484d602206bbb8e8cf1b2a6e8 ea64f78f7d7625d05014f593c76438c7127d5e2b147d971601210279be667ef9dcbbac55a06295c e870b07029bfcdb2dce28d959f2815b16f81798ffffffff023997ef27000000001976a914751e76 e8199196d454941c45d1b3a323f1433bd688acafb2f501000000001976a914f6f5431d25bbf7b12 e8add9af5e3475c44a0a5b888ac00000000


Cheers Grin


Did u test it? Do you have a example that it worked out?