You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

校园项目自定义Bitcoin矿工:候选区块创建与提交方法及代码优化咨询

Hey there! Let's break down your questions step by step—building a Bitcoin miner for a campus project is a fantastic learning deep dive, so props for taking this on. I'll cover both creating/submitting candidate blocks and some solid code optimizations to make your miner more efficient.

Creating & Submitting a Candidate Block

Bitcoin blocks have a strict structure that your code needs to replicate before you can mine and submit one. Here's what you're missing:

Step 1: Understand the Full Block Structure

A valid Bitcoin block includes these core fields:

  • Version: A number indicating the block protocol version (e.g., 0x20000000 for modern Bitcoin)
  • Previous Block Hash: The hash of the prior block in the chain (you have this already)
  • Merkle Root: A single hash that summarizes all transactions in the block (critical—your current code just concatenates transactions, which isn't how Bitcoin does it)
  • Timestamp: Unix timestamp when the block is created
  • Difficulty Target: The required number of leading zeros (you're using prefix_zeros, which is a simplified version)
  • Nonce: The number you're brute-forcing to get a valid hash

Step 2: Build the Block Header

To create a candidate block:

  1. Collect & Structure Transactions: Use your transactiongetter to gather transactions, then format them into a list of strings (or objects) instead of a hardcoded string. For a campus project, you can skip full signature validation but should ensure each transaction follows a consistent format.
  2. Compute the Merkle Root: Take all transaction hashes, pair them up, hash each pair, and repeat until you have one final hash (the Merkle root). This lets nodes quickly verify transactions without downloading the entire set.
  3. Fill the Header: Combine all the fields above into a single string/byte stream. This is what you'll hash with the nonce to find a valid block.

Step 3: Submit the Block

In the real Bitcoin network, you'd broadcast the valid block to connected nodes, which then verify it and add it to their chain. For your project:

  • Create a simple "simulated node" function that checks if the block header hash meets the difficulty target, validates the Merkle root matches the transactions, and adds it to a local chain.
  • You don't need to connect to the real Bitcoin network—focus on simulating the validation and chain storage logic for your project.
Code Optimization Suggestions

Your current code works, but here are some tweaks to make it faster and more aligned with real Bitcoin logic:

1. Optimize Hash Calculation

Your SHA256 function encodes text every time, which is inefficient. Instead, precompute the static part of the header and work with bytes where possible:

from hashlib import sha256
import time

MAX_NONCE = 100000000000

def SHA256(data):
    if isinstance(data, str):
        data = data.encode("ascii")
    return sha256(data).hexdigest()

# Precompute static header parts to avoid redundant string concatenation
def mine(block_number, merkle_root, previous_hash, prefix_zeros):
    prefix_str = '0' * prefix_zeros
    static_header = f"{block_number}{merkle_root}{previous_hash}"
    for nonce in range(MAX_NONCE):
        text = f"{static_header}{nonce}"
        new_hash = SHA256(text)
        if new_hash.startswith(prefix_str):
            print(f"Yay! Successfully mined with nonce value: {nonce}")
            return new_hash, nonce
    raise Exception(f"Tried {MAX_NONCE} times and failed to find a valid nonce")

2. Add Proper Merkle Root Calculation

Replace your hardcoded transaction string with a Merkle root (this is how Bitcoin actually summarizes transactions):

def compute_merkle_root(transactions):
    if not transactions:
        return SHA256("")
    # Hash each individual transaction first
    hashes = [SHA256(tx) for tx in transactions]
    # Iteratively combine hashes until one remains
    while len(hashes) > 1:
        # Handle odd number of hashes by duplicating the last one
        if len(hashes) % 2 != 0:
            hashes.append(hashes[-1])
        new_hashes = []
        for i in range(0, len(hashes), 2):
            combined = hashes[i] + hashes[i+1]
            new_hashes.append(SHA256(combined))
        hashes = new_hashes
    return hashes[0]

3. Parallelize Nonce Brute-Forcing

Brute-forcing nonces is CPU-intensive—use multi-processing to split the work across your machine's cores:

from multiprocessing import Pool

def mine_worker(args):
    block_number, merkle_root, previous_hash, prefix_zeros, nonce_range = args
    prefix_str = '0' * prefix_zeros
    static_header = f"{block_number}{merkle_root}{previous_hash}"
    for nonce in nonce_range:
        text = f"{static_header}{nonce}"
        new_hash = SHA256(text)
        if new_hash.startswith(prefix_str):
            return (new_hash, nonce)
    return None

def mine_parallel(block_number, merkle_root, previous_hash, prefix_zeros, num_processes=4):
    chunk_size = MAX_NONCE // num_processes
    nonce_ranges = []
    for i in range(num_processes):
        start = i * chunk_size
        end = start + chunk_size if i != num_processes-1 else MAX_NONCE
        nonce_ranges.append((block_number, merkle_root, previous_hash, prefix_zeros, range(start, end)))
    
    with Pool(num_processes) as pool:
        results = pool.map(mine_worker, nonce_ranges)
    
    for result in results:
        if result is not None:
            print(f"Yay! Successfully mined with nonce value: {result[1]}")
            return result
    raise Exception(f"Tried {MAX_NONCE} times and failed to find a valid nonce")

4. Clean Up Transaction Handling

Avoid relying on global variables from transactiongetter—pass transactions explicitly for better readability:

from transactiongetter import inp, inpbit, out, outbit

if __name__ == '__main__':
    # Structure transactions into a list instead of a hardcoded string
    transactions = [f"{tx_in} -> {tx_out} -> {tx_inbit}" for tx_in, tx_out, tx_inbit in zip(inp, out, inpbit)]
    merkle_root = compute_merkle_root(transactions)
    difficulty = 5  # Higher number = more difficulty
    start = time.time()
    print("Start mining...")
    # Use either mine() or mine_parallel() here
    new_hash, nonce = mine(5, merkle_root, '0000000xa036944e29568d0cff17edbe038f81208fecf9a66be9a2b8321c6ec7', difficulty)
    total_time = time.time() - start
    print(f"End mining. Mining took: {total_time:.2f} seconds")
    print(f"Block hash: {new_hash}")
    print(f"Nonce: {nonce}")
Final Notes

For your campus project, focus on simulating the core logic rather than connecting to the real Bitcoin network—full node integration is way more complex. Start with a local chain, add block validation, and expand features like difficulty adjustment if you have extra time.

内容的提问来源于stack exchange,提问作者Frantisek Mach

火山引擎 最新活动