2024-10-02 19:07:07 +02:00
|
|
|
|
##SN PyBlock Miner##
|
|
|
|
|
|
|
2024-10-02 03:55:03 +02:00
|
|
|
|
import requests
|
|
|
|
|
|
import hashlib
|
|
|
|
|
|
import binascii
|
|
|
|
|
|
import json
|
Security audit round 2: eliminate shell=True, mask secrets, fix race conditions
- Replace all shell=True subprocess calls with Python-native processing
(nodeconnection.py, SPV/nodeconnection.py, SPV/ppi.py)
- Mask sensitive inputs (private keys, passwords, tokens) with getpass
- Add threading.Lock to block_explorer.py shared state
- Use json.loads() instead of fragile string splitting in apisnd.py
- Add path validation before file open in apisnd.py
- Replace random.randint with secrets.randbelow for mining nonces
- Fix destructive exception handlers in clone.py and feed.py
- Replace bare except clauses with specific exceptions + logging
- Remove unused imports (psutil, xmltodict, block_visualizer, base64, say)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 11:15:59 -03:00
|
|
|
|
import secrets
|
2024-10-02 03:55:03 +02:00
|
|
|
|
import socket
|
|
|
|
|
|
import time
|
|
|
|
|
|
from threading import Thread
|
|
|
|
|
|
from colorthon import Colors as Fore
|
|
|
|
|
|
import sys, logging
|
2024-10-02 03:58:46 +02:00
|
|
|
|
import signal
|
2024-10-02 03:55:03 +02:00
|
|
|
|
signal.signal(signal.SIGINT, lambda x, y: sys.exit(0))
|
|
|
|
|
|
|
|
|
|
|
|
# Define your Bitcoin address
|
|
|
|
|
|
address = "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa.SatoshiNakamoto"
|
|
|
|
|
|
# Initialize the current block height
|
|
|
|
|
|
cHeight = 0
|
|
|
|
|
|
solopyblockminer = '''
|
2024-10-02 15:10:08 +02:00
|
|
|
|
⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣴⣶⣾⣿⣿⣿⣿⣷⣶⣦⣤⣀
|
|
|
|
|
|
⠀⠀⠀⠀⠀⣠⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣄
|
|
|
|
|
|
⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄
|
|
|
|
|
|
⠀⠀⣴⣿⣿⣿⣿⣿⣿⣿⠟⠿⠿⡿⠀⢰⣿⠁⢈⣿⣿⣿⣿⣿⣿⣿⣿⣦
|
|
|
|
|
|
⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣤⣄⠀⠀⠀⠈⠉⠀⠸⠿⣿⣿⣿⣿⣿⣿⣿⣿⣧
|
2024-10-02 04:30:13 +02:00
|
|
|
|
⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡏⠀⠀⢠⣶⣶⣤⡀⠀⠈⢻⣿⣿⣿⣿⣿⣿⣿⡆
|
|
|
|
|
|
⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃⠀⠀⠼⣿⣿⡿⠃⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣷
|
|
|
|
|
|
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⢀⣀⣀⠀⠀⠀⠀⢴⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
|
|
|
|
⢿⣿⣿⣿⣿⣿⣿⣿⢿⣿⠁⠀⠀⣼⣿⣿⣿⣦⠀⠀⠈⢻⣿⣿⣿⣿⣿⣿⣿⡿
|
|
|
|
|
|
⠸⣿⣿⣿⣿⣿⣿⣏⠀⠀⠀⠀⠀⠛⠛⠿⠟⠋⠀⠀⠀⣾⣿⣿⣿⣿⣿⣿⣿⠇
|
2024-10-02 15:10:08 +02:00
|
|
|
|
⠀⢻⣿⣿⣿⣿⣿⣿⣿⣿⠇⠀⣤⡄⠀⣀⣀⣀⣀⣠⣾⣿⣿⣿⣿⣿⣿⣿⡟
|
|
|
|
|
|
⠀⠀⠻⣿⣿⣿⣿⣿⣿⣿⣄⣰⣿⠁⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟
|
|
|
|
|
|
⠀⠀⠀⠙⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠋
|
|
|
|
|
|
⠀⠀⠀⠀⠀⠙⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠋
|
|
|
|
|
|
⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠻⠿⢿⣿⣿⣿⣿⡿⠿⠟⠛⠉
|
2024-10-02 04:30:13 +02:00
|
|
|
|
M I N I N G
|
|
|
|
|
|
B I T C O I N⠀
|
2024-10-02 03:55:03 +02:00
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
def delay_print(s):
|
|
|
|
|
|
for c in s:
|
|
|
|
|
|
sys.stdout.write(c)
|
|
|
|
|
|
sys.stdout.flush()
|
|
|
|
|
|
time.sleep(0.1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
print(Fore.RED, solopyblockminer, Fore.RESET)
|
|
|
|
|
|
cHeight = 0
|
|
|
|
|
|
inpAdd = input(
|
2024-10-02 05:19:07 +02:00
|
|
|
|
f'{Fore.MAGENTA}[*]{Fore.RESET}{Fore.WHITE} INSERT HERE YOUR BITCOIN WALLET ADDRESS{Fore.RESET} : ')
|
2024-10-02 03:55:03 +02:00
|
|
|
|
address = str(inpAdd)
|
|
|
|
|
|
print(f'\n{Fore.GREY}Bitcoin Wallet Address{Fore.RESET} ===>> {Fore.MAGENTA}{address}{Fore.RESET}')
|
|
|
|
|
|
print(f"{Fore.GREY}{'-' * 66}{Fore.RESET}")
|
2024-10-02 05:19:07 +02:00
|
|
|
|
delay_print('Bitcoin Wallet Address Added. ... Mining Now ...')
|
2024-10-02 03:55:03 +02:00
|
|
|
|
print(f"\n{Fore.GREY}{'-' * 66}{Fore.RESET}")
|
|
|
|
|
|
|
|
|
|
|
|
time.sleep(3)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def logg(msg):
|
|
|
|
|
|
logging.basicConfig(level=logging.INFO, filename="miner.log", format='%(asctime)s %(message)s') # include timestamp
|
|
|
|
|
|
logging.info(msg)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Function to get the current network block height
|
|
|
|
|
|
def get_current_block_height():
|
|
|
|
|
|
r = requests.get('https://blockchain.info/latestblock')
|
|
|
|
|
|
return int(r.json()['height'])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Function for the mining process
|
|
|
|
|
|
def BitcoinMiner(restart=False):
|
|
|
|
|
|
# Function to handle the mining process
|
|
|
|
|
|
|
|
|
|
|
|
if restart:
|
|
|
|
|
|
time.sleep(2)
|
|
|
|
|
|
logg('[*] Bitcoin Miner Restarted')
|
|
|
|
|
|
else:
|
|
|
|
|
|
logg('[*] Bitcoin Miner Started')
|
|
|
|
|
|
print('[*] Bitcoin Miner Started')
|
|
|
|
|
|
|
|
|
|
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
2026-08-13 02:02:05 +02:00
|
|
|
|
sock.connect(('pool110.pyblock.xyz', 4445))
|
2024-10-02 03:55:03 +02:00
|
|
|
|
|
|
|
|
|
|
sock.sendall(b'{"id": 1, "method": "mining.subscribe", "params": []}\n')
|
|
|
|
|
|
|
|
|
|
|
|
lines = sock.recv(1024).decode().split('\n')
|
|
|
|
|
|
|
|
|
|
|
|
response = json.loads(lines[0])
|
|
|
|
|
|
sub_details, extranonce1, extranonce2_size = response['result']
|
|
|
|
|
|
|
|
|
|
|
|
sock.sendall(b'{"params": ["' + address.encode() + b'", "password"], "id": 2, "method": "mining.authorize"}\n')
|
|
|
|
|
|
|
|
|
|
|
|
response = b''
|
|
|
|
|
|
while response.count(b'\n') < 4 and not (b'mining.notify' in response): response += sock.recv(1024)
|
|
|
|
|
|
|
|
|
|
|
|
responses = [json.loads(res) for res in response.decode().split('\n') if
|
|
|
|
|
|
len(res.strip()) > 0 and 'mining.notify' in res]
|
|
|
|
|
|
job_id, prevhash, coinb1, coinb2, merkle_branch, version, nbits, ntime, clean_jobs = responses[0]['params']
|
|
|
|
|
|
target = (nbits[2:] + '00' * (int(nbits[:2], 16) - 3)).zfill(64)
|
Security audit round 2: eliminate shell=True, mask secrets, fix race conditions
- Replace all shell=True subprocess calls with Python-native processing
(nodeconnection.py, SPV/nodeconnection.py, SPV/ppi.py)
- Mask sensitive inputs (private keys, passwords, tokens) with getpass
- Add threading.Lock to block_explorer.py shared state
- Use json.loads() instead of fragile string splitting in apisnd.py
- Add path validation before file open in apisnd.py
- Replace random.randint with secrets.randbelow for mining nonces
- Fix destructive exception handlers in clone.py and feed.py
- Replace bare except clauses with specific exceptions + logging
- Remove unused imports (psutil, xmltodict, block_visualizer, base64, say)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 11:15:59 -03:00
|
|
|
|
extranonce2 = hex(secrets.randbelow(2 ** 32))[2:].zfill(2 * extranonce2_size) # create random
|
2024-10-02 03:55:03 +02:00
|
|
|
|
|
|
|
|
|
|
coinbase = coinb1 + extranonce1 + extranonce2 + coinb2
|
|
|
|
|
|
coinbase_hash_bin = hashlib.sha256(hashlib.sha256(binascii.unhexlify(coinbase)).digest()).digest()
|
|
|
|
|
|
|
|
|
|
|
|
merkle_root = coinbase_hash_bin
|
|
|
|
|
|
for h in merkle_branch:
|
|
|
|
|
|
merkle_root = hashlib.sha256(hashlib.sha256(merkle_root + binascii.unhexlify(h)).digest()).digest()
|
|
|
|
|
|
|
|
|
|
|
|
merkle_root = binascii.hexlify(merkle_root).decode()
|
|
|
|
|
|
|
|
|
|
|
|
merkle_root = ''.join([merkle_root[i] + merkle_root[i + 1] for i in range(0, len(merkle_root), 2)][::-1])
|
|
|
|
|
|
|
|
|
|
|
|
work_on = get_current_block_height()
|
2024-10-04 00:01:08 +02:00
|
|
|
|
print(Fore.GREEN, '\n Working on current Network height', Fore.WHITE, work_on)
|
2024-10-02 03:55:03 +02:00
|
|
|
|
print(Fore.YELLOW, 'Current TARGET =', Fore.RED, target)
|
|
|
|
|
|
z = 0
|
|
|
|
|
|
while True:
|
|
|
|
|
|
if cHeight > work_on:
|
|
|
|
|
|
logg('[*] Restarting Miner')
|
|
|
|
|
|
BitcoinMiner(restart=True)
|
|
|
|
|
|
break
|
|
|
|
|
|
|
Security audit round 2: eliminate shell=True, mask secrets, fix race conditions
- Replace all shell=True subprocess calls with Python-native processing
(nodeconnection.py, SPV/nodeconnection.py, SPV/ppi.py)
- Mask sensitive inputs (private keys, passwords, tokens) with getpass
- Add threading.Lock to block_explorer.py shared state
- Use json.loads() instead of fragile string splitting in apisnd.py
- Add path validation before file open in apisnd.py
- Replace random.randint with secrets.randbelow for mining nonces
- Fix destructive exception handlers in clone.py and feed.py
- Replace bare except clauses with specific exceptions + logging
- Remove unused imports (psutil, xmltodict, block_visualizer, base64, say)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 11:15:59 -03:00
|
|
|
|
nonce = hex(secrets.randbelow(2 ** 32))[2:].zfill(8) # nnonve #hex(int(nonce,16)+1)[2:]
|
2024-10-02 03:55:03 +02:00
|
|
|
|
blockheader = version + prevhash + merkle_root + nbits + ntime + nonce + \
|
|
|
|
|
|
'000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000'
|
|
|
|
|
|
hash = hashlib.sha256(hashlib.sha256(binascii.unhexlify(blockheader)).digest()).digest()
|
|
|
|
|
|
hash = binascii.hexlify(hash).decode()
|
|
|
|
|
|
|
|
|
|
|
|
if hash.startswith('000000000000000000000'): logg('hash: {}'.format(hash))
|
|
|
|
|
|
print(Fore.GREEN, str(z), ' HASH :', Fore.YELLOW, ' 000000000000000000000{}'.format(hash), end='\r')
|
|
|
|
|
|
z += 1
|
|
|
|
|
|
if hash.startswith('000000000000000000'): logg('hash: {}'.format(hash))
|
|
|
|
|
|
z += 1
|
|
|
|
|
|
|
|
|
|
|
|
print(Fore.YELLOW, str(z), 'HASH :', Fore.RED, ' 000000000000000000{}'.format(hash), end='\r')
|
|
|
|
|
|
z += 1
|
|
|
|
|
|
|
|
|
|
|
|
if hash.startswith('000000000000000'): logg('hash: {}'.format(hash))
|
|
|
|
|
|
print(Fore.BLUE, str(z), 'HASH :', Fore.GREEN, ' 000000000000000{}'.format(hash), end='\r')
|
|
|
|
|
|
z += 1
|
|
|
|
|
|
|
|
|
|
|
|
if hash.startswith('000000000000'): logg('hash: {}'.format(hash))
|
|
|
|
|
|
print(Fore.MAGENTA, str(z), 'HASH :', Fore.YELLOW, ' 000000000000{}'.format(hash), end='\r')
|
|
|
|
|
|
z += 1
|
|
|
|
|
|
|
|
|
|
|
|
if hash.startswith('0000000'): logg('hash: {}'.format(hash))
|
|
|
|
|
|
print(Fore.CYAN, str(z), 'HASH :', Fore.YELLOW, '0000000{}'.format(hash), end='\r')
|
|
|
|
|
|
z += 1
|
|
|
|
|
|
|
|
|
|
|
|
if hash < target:
|
|
|
|
|
|
print('[*] New block mined')
|
|
|
|
|
|
logg('[*] success!!')
|
|
|
|
|
|
logg(blockheader)
|
|
|
|
|
|
logg('hash: {}'.format(hash))
|
|
|
|
|
|
|
|
|
|
|
|
payload = bytes(
|
|
|
|
|
|
'{"params": ["' + address + '", "' + job_id + '", "' + extranonce2 \
|
|
|
|
|
|
+ '", "' + ntime + '", "' + nonce + '"], "id": 1, "method": "mining.submit"}\n', 'utf-8')
|
|
|
|
|
|
sock.sendall(payload)
|
|
|
|
|
|
logg(payload)
|
|
|
|
|
|
ret = sock.recv(1024)
|
|
|
|
|
|
logg(ret)
|
|
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Function to listen for new blocks
|
|
|
|
|
|
def newBlockListener():
|
|
|
|
|
|
global cHeight
|
|
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
|
network_height = get_current_block_height()
|
|
|
|
|
|
|
|
|
|
|
|
if network_height > cHeight:
|
|
|
|
|
|
logg('[*] Network has new height %d ' % network_height)
|
|
|
|
|
|
logg('[*] Our local is %d' % cHeight)
|
|
|
|
|
|
cHeight = network_height
|
|
|
|
|
|
logg('[*] Our new local after update is %d' % cHeight)
|
|
|
|
|
|
|
|
|
|
|
|
# respect Api
|
|
|
|
|
|
time.sleep(40)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Main function to start the miner and block listener
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
|
# Start the block listener and miner threads
|
|
|
|
|
|
Thread(target=newBlockListener).start()
|
|
|
|
|
|
time.sleep(2)
|
|
|
|
|
|
Thread(target=BitcoinMiner).start()
|