Pages:
Author

Topic: Bitcoin Core + Solo Mining Program - page 2. (Read 377 times)

legendary
Activity: 1512
Merit: 7340
Farewell, Leo
January 29, 2025, 10:30:17 AM
#11
By the way, do you know a lot of people who solo mine? I know none and I always felt the urge to try it.
It's fun, but it's just gambling. In fact, depending on your equipment, winning the lottery can actually be more profitable than finding a block within several years.

For example, let's take NotFuzzyWarm's numbers. Current target is:
Code:
000000000000000000029a8a0000000000000000000000000000000000000000

To get the probability of finding a block at once (one hash), divide it by 2^256.
Code:
$ echo "ibase=16; $(echo 000000000000000000029a8a0000000000000000000000000000000000000000 | tr 'a-f' 'A-F')" | bc
249381870384321288544767557745710236775970393538166784
$ echo "ibase=16; $(echo ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | tr 'a-f' 'A-F')" | bc
115792089237316195423570985008687907853269984665640564039457584007913129639935
$ echo "scale=50; 249381870384321288544767557745710236775970393538166784 / 115792089237316195423570985008687907853269984665640564039457584007913129639935" | bc
.00000000000000000000000215370386722371405447399827

Therefore, the probability of not finding a block at once, would be 0.99999999999999999999999784629613277628594552600173.

With 150 TH/s, the probability of not finding a block within a second would be:
Code:
0.99999999999999999999999784629613277628594552600173^150000000000000

To calculate this with high precision, you need to make use of special libraries:
Code:
from mpmath import mp

mp.dps = 100 # precision
a = mp.mpf('0.99999999999999999999999784629613277628594552600173') # probability of not finding a block at once
b = 150000000000000 # hashrate


# probability that you won't find a block in one second
result = mp.power(a, b)
print("Probability that you find a block in one second: ", 1-result)

# probability that you won't find a block in one minute
result = mp.power(result, 60)
print("Probability that you find a block in one minute: ", 1-result)

# probability that you won't find a block in one hour
result = mp.power(result, 60)
print("Probability that you find a block in one hour: ", 1-result)

# probability that you won't find a block in one day
result = mp.power(result, 24)
print("Probability that you find a block in one day: ", 1-result)

# probability that you won't find a block in 365 days
result = mp.power(result, 365)
print("Probability that you find a block in 365 days: ", 1-result)

Results:
Code:
$ python script.py
Probability that you find a block in one second:  0.0000000003230555800313746542651575759752715614541821047547449121224850649399499116300689485485483766011969696
Probability that you find a block in one minute:  0.00000001938333461715659362240752539068268809022908905282234609174506460595343787394574728284894247787867632
Probability that you find a block in one hour:  0.000001162999412016465068516484322398343389488271846415173949033771762598140719659379694685549553920155671
Probability that you find a block in one day:  0.00002791161258291243699820616307956869968979018852187562446262529145259602086639222189814513684159590908
Probability that you find a block in 365 days:  0.0101361601065333352625712188251736971051205876315052582934340097318939980049579694902996727303243481

Those numbers are not totally accurate, of course, because of difficulty adjustments. Given that difficulty is leaning upwards, the probability of mining a block within a year becomes even less than 1% overtime, with the same hashrate.
legendary
Activity: 3822
Merit: 2703
Evil beware: We have waffles!
January 29, 2025, 09:48:09 AM
#10
Hello. What is your equipment, if I may ask?
Mainly Canaan Avalons: A1246 and A1047 and a Nano-3. Also an ancient Bitmain R4 along with Sidehack's Compac-F and Compac-A1.

Since starting in 2014 I've found 10 blocks but all were using PPLNS on Kano's pool. I switched to solo just for 1 final Big Score...
hero member
Activity: 686
Merit: 1360
✔️ CoinJoin Wallet
January 29, 2025, 03:00:09 AM
#9
That said, I solo mine at Kano.is with 150 THs pointed there. Also, for reference - been doing that for 3 years and still no block. Wink

Hello. What is your equipment, if I may ask?
full member
Activity: 938
Merit: 206
web developer for hire
January 28, 2025, 08:11:31 PM
#8
If you're doing this because you wanted to make a program you've succeeded. It won't have use because solo mining isn't going to bring blocks so who's going to use it ?

I installed Bitcoin Core on my laptop, synchronized it, and successfully ran it. Additionally, I developed a Python program to perform solo mining by connecting to Bitcoin Core via RPC.
legendary
Activity: 3822
Merit: 2703
Evil beware: We have waffles!
January 28, 2025, 04:59:25 PM
#7
You REALLY should ref https://bitcointalksearch.org/topic/bitcoin-mining-intro-rules-of-this-subforum-read-before-posting-2415854 point-3....
Solo mining even with state-of-the-art miners or by renting a massive amount of hash rate has very very VERY long odds against you. Playing at "mining" with a CPU or GPU or even FPGA rigs puts the odds at MAYBE once in the lifetime of the universe.....

I doubt that you can even be able to process 1 share during the 10min average time of blocks being found and new work started.

That said, I solo mine at Kano.is with 150 THs pointed there. Also, for reference - been doing that for 3 years and still no block. Wink
hero member
Activity: 686
Merit: 1360
✔️ CoinJoin Wallet
January 28, 2025, 03:35:40 PM
#6
It can even be used with a CPU.

Using cpuminer-opt: https://github.com/JayDDee/cpuminer-opt.
Code:
./cpuminer --algo sha256d --coinbase-addr=
--userpass=USER:PASS -o stratum+tcp://192.168.x.y:3333

USER and PASS are credentials of CKpool. CPU miner connects to pool via stratum and receives block templates.

I will try it for fun.
By the way, do you know a lot of people who solo mine? I know none and I always felt the urge to try it.
legendary
Activity: 1512
Merit: 7340
Farewell, Leo
January 28, 2025, 02:41:25 PM
#5
Can it be used with small solo mining devices like Mars Lander or
Gekkoscience R909
?
It can even be used with a CPU.

Using cpuminer-opt: https://github.com/JayDDee/cpuminer-opt.
Code:
./cpuminer --algo sha256d --coinbase-addr=
--userpass=USER:PASS -o stratum+tcp://192.168.x.y:3333

USER and PASS are credentials of CKpool. CPU miner connects to pool via stratum and receives block templates.
hero member
Activity: 686
Merit: 1360
✔️ CoinJoin Wallet
January 28, 2025, 02:16:55 PM
#4
but there is already optimized mining software for that purpose, like CKpool.

Doesn't this require an ASIC to work?
Can it be used with small solo mining devices like Mars Lander or
Gekkoscience R909
?
legendary
Activity: 1512
Merit: 7340
Farewell, Leo
January 28, 2025, 10:46:41 AM
#3
It would be greatly helpful if you could review my program and let me know if there are any issues or potential improvements.
Yes, to not use python.  Cheesy

If what you're trying to accomplish is just test your mining program, then you can use testnet4 and see if it's working properly. From a quick glimpse it seems theoretically correct, but there is already optimized mining software for that purpose, like CKpool.

Edit: CKpool with CPU miner software, like cpuminer-opt, as shown below.
hero member
Activity: 686
Merit: 1360
✔️ CoinJoin Wallet
January 28, 2025, 10:34:18 AM
#2
Please, use code brackets like this:

Code:
#put code here

I will review the code later today, but again, please learn and use proper bbcode tags.
?
Activity: -
Merit: -
January 28, 2025, 02:00:33 AM
#1
I installed Bitcoin Core on my laptop, synchronized it, and successfully ran it. Additionally, I developed a Python program to perform solo mining by connecting to Bitcoin Core via RPC.

In this program, I implemented an algorithm that generates various nonce values and applies them to the mining process. While I am aware that the probability of successfully mining a block is extremely low, I would like to confirm whether my solo mining Python program is technically correct and operates without errors on the actual Bitcoin network.

It would be greatly helpful if you could review my program and let me know if there are any issues or potential improvements. I sincerely appreciate your time and assistance with this request.

Thank you once again, and I look forward to your response.


import hashlib
import requests
import json
import struct
import time
import random

# RPC settings
RPC_USER = "user"
RPC_PASSWORD = "passwd"
RPC_URL = "http://127.0.0.1:8332/"

# User-defined address
MINING_ADDRESS = "your_bitcoin_address"

def is_valid_bitcoin_address(address):
    """Validate the Bitcoin address"""
    try:
        alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
        base58_decoded = 0
        for char in address:
            base58_decoded = base58_decoded * 58 + alphabet.index(char)
        address_bytes = base58_decoded.to_bytes(25, byteorder="big")
        checksum = address_bytes[-4:]
        hash_checksum = hashlib.sha256(hashlib.sha256(address_bytes[:-4]).digest()).digest()[:4]
        return checksum == hash_checksum
    except Exception as e:
        print(f"Address validation failed: {e}")
        return False

# Validate MINING_ADDRESS
if not is_valid_bitcoin_address(MINING_ADDRESS):
    raise ValueError(f"Invalid Bitcoin address: {MINING_ADDRESS}")

def rpc_request(method, params=None):
    """Send an RPC request"""
    payload = json.dumps({"jsonrpc": "2.0", "id": "mining", "method": method, "params": params or []})
    response = requests.post(RPC_URL, auth=(RPC_USER, RPC_PASSWORD), data=payload)
    try:
        response.raise_for_status()
        result = response.json()
        if "result" not in result:
            raise ValueError("The 'result' field is missing in the RPC response.")
        return result["result"]
    except Exception as e:
        print(f"RPC request failed: {e}")
        print(f"Response content: {response.text}")
        raise

def address_to_script_pubkey(address):
    """Convert Bitcoin address to ScriptPubKey"""
    try:
        alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
        base58_decoded = 0
        for char in address:
            base58_decoded = base58_decoded * 58 + alphabet.index(char)
        address_bytes = base58_decoded.to_bytes(25, byteorder="big")
        print(f"Base58 decoding successful: {address_bytes.hex()}")
        pubkey_hash = address_bytes[1:-4]  # Exclude network byte and checksum
        script_pubkey = b"\x76\xa9" + bytes([len(pubkey_hash)]) + pubkey_hash + b"\x88\xac"
        print(f"ScriptPubKey generated successfully: {script_pubkey.hex()}")
        return script_pubkey
    except Exception as e:
        print(f"Address conversion failed: {e}")
        raise

def modify_coinbase_tx(block_template, extra_nonce):
    """Generate a coinbase transaction"""
    coinbase_value = block_template["coinbasevalue"]
    script_pubkey = address_to_script_pubkey(MINING_ADDRESS)
    extra_nonce_script = struct.pack("    script_pubkey = extra_nonce_script + script_pubkey
    coinbase_tx = (
        b"\x01"
        b"\x00"
        b"\x01"
        + b"\x00" * 32
        + b"\xff" * 4
        + b"\x01"
        + struct.pack("        + struct.pack("B", len(script_pubkey))
        + script_pubkey
    )
    return coinbase_tx

def calculate_merkle_root(transactions):
    """Calculate the Merkle root"""
    transaction_hashes = [hashlib.sha256(bytes.fromhex(tx["data"])).digest() for tx in transactions]
    while len(transaction_hashes) > 1:
        if len(transaction_hashes) % 2 == 1:  # Duplicate the last hash if odd
            transaction_hashes.append(transaction_hashes[-1])
        transaction_hashes = [
            hashlib.sha256(transaction_hashes + transaction_hashes[i + 1]).digest()
            for i in range(0, len(transaction_hashes), 2)
        ]
    return transaction_hashes[0][::-1]  # Return little-endian

def calculate_block_hash(header):
    """Generate a block hash by hashing the block header"""
    hash1 = hashlib.sha256(header).digest()
    hash2 = hashlib.sha256(hash1).digest()
    return hash2[::-1]  # Return little-endian

def mine():
    """Mining loop"""
    print("Starting Bitcoin mining...")
    extra_nonce = 0  # Initialize Extra Nonce

    while True:
        try:
            block_template = rpc_request("getblocktemplate", [{"rules": ["segwit"]}])
            previous_block = block_template["previousblockhash"]
            target = int(block_template["target"], 16)
            print(f"Mining target: {block_template['target']}")

            while True:  # Extra Nonce loop
                coinbase_tx = modify_coinbase_tx(block_template, extra_nonce)
                transactions = [{"data": coinbase_tx.hex()}] + block_template["transactions"]

                merkle_root = calculate_merkle_root(transactions)

                version = struct.pack("                prev_block_hash = bytes.fromhex(previous_block)[::-1]
                ntime = struct.pack("                nbits = bytes.fromhex(block_template["bits"])[::-1]
                nonce = 0

                while nonce < 2**32:  # Nonce range
                    header = (
                        version
                        + prev_block_hash
                        + merkle_root
                        + ntime
                        + nbits
                        + struct.pack("                    )
                    block_hash = calculate_block_hash(header)

                    if int(block_hash.hex(), 16) < target:
                        print(f"Mining successful! Block hash: {block_hash.hex()}")
                        print(f"Extra Nonce: {extra_nonce}, Nonce: {nonce}")

                        result = rpc_request("submitblock", [header.hex()])
                        if result is None:
                            print("Block successfully submitted!")
                        else:
                            print(f"Block submission failed: {result}")
                        return  # Exit mining loop

                    nonce += 1

                # Increase Extra Nonce when nonce is exhausted
                print(f"Nonce exhausted - Increasing Extra Nonce: {extra_nonce}")
                extra_nonce += 1

        except Exception as e:
            print(f"Error occurred: {e}")
            time.sleep(5)

if __name__ == "__main__":
    mine()
Pages:
Jump to: