44import struct
55import time
66import os
7+ import base64
8+ import http .client
79
810def get_input (prompt , data_type = str ):
911 while True :
@@ -14,27 +16,46 @@ def get_input(prompt, data_type=str):
1416 print (f"Invalid input. Please enter a valid { data_type .__name__ } ." )
1517
1618if os .path .isfile ('config.json' ):
17- print ("config.json found,start mining" )
19+ print ("config.json found, start mining" )
1820 with open ('config.json' ,'r' ) as file :
1921 config = json .load (file )
22+ connection_type = config .get ("connection_type" , "stratum" )
2023 pool_address = config ['pool_address' ]
2124 pool_port = config ["pool_port" ]
2225 username = config ["user_name" ]
2326 password = config ["password" ]
2427 min_diff = config ["min_diff" ]
28+ rpc_user = config .get ("rpc_user" , "" )
29+ rpc_password = config .get ("rpc_password" , "" )
30+ rpc_port = config .get ("rpc_port" , 8332 )
2531else :
26- print ("config.json doesn't exist,generating now" )
32+ print ("config.json doesn't exist, generating now" )
33+ connection_type = get_input ("Enter connection type (stratum/rpc): " ).lower ()
2734 pool_address = get_input ("Enter the pool address: " )
2835 pool_port = get_input ("Enter the pool port: " , int )
2936 user_name = get_input ("Enter the user name: " )
3037 password = get_input ("Enter the password: " )
3138 min_diff = get_input ("Enter the minimum difficulty: " , float )
39+
40+ if connection_type == "rpc" :
41+ rpc_user = get_input ("Enter Bitcoin RPC username: " )
42+ rpc_password = get_input ("Enter Bitcoin RPC password: " )
43+ rpc_port = get_input ("Enter Bitcoin RPC port (default 8332): " , int ) or 8332
44+ else :
45+ rpc_user = ""
46+ rpc_password = ""
47+ rpc_port = 8332
48+
3249 config_data = {
50+ "connection_type" : connection_type ,
3351 "pool_address" : pool_address ,
3452 "pool_port" : pool_port ,
3553 "user_name" : user_name ,
3654 "password" : password ,
37- "min_diff" : min_diff
55+ "min_diff" : min_diff ,
56+ "rpc_user" : rpc_user ,
57+ "rpc_password" : rpc_password ,
58+ "rpc_port" : rpc_port
3859 }
3960 with open ("config.json" , "w" ) as config_file :
4061 json .dump (config_data , config_file , indent = 4 )
@@ -59,6 +80,32 @@ def connect_to_pool(pool_address, pool_port, timeout=30, retries=5):
5980
6081 raise Exception ("Failed to connect to the pool after multiple attempts" )
6182
83+ def connect_to_bitcoin_rpc (rpc_user , rpc_password , rpc_host = "127.0.0.1" , rpc_port = 8332 , timeout = 30 ):
84+ auth = base64 .b64encode (f"{ rpc_user } :{ rpc_password } " .encode ()).decode ('utf-8' )
85+ headers = {
86+ "Authorization" : f"Basic { auth } " ,
87+ "Content-Type" : "application/json"
88+ }
89+
90+ conn = http .client .HTTPConnection (rpc_host , port = rpc_port , timeout = timeout )
91+ return conn , headers
92+
93+ def send_rpc_request (conn , headers , method , params = None ):
94+ if params is None :
95+ params = []
96+
97+ payload = {
98+ "jsonrpc" : "1.0" ,
99+ "id" : "python_miner" ,
100+ "method" : method ,
101+ "params" : params
102+ }
103+
104+ conn .request ("POST" , "/" , json .dumps (payload ), headers )
105+ response = conn .getresponse ()
106+ data = response .read ().decode ('utf-8' )
107+ return json .loads (data )
108+
62109def send_message (sock , message ):
63110 print (f"Sending message: { message } " )
64111 sock .sendall ((json .dumps (message ) + '\n ' ).encode ('utf-8' ))
@@ -149,25 +196,50 @@ def submit_solution(sock, job_id, extranonce2, ntime, nonce):
149196 print (f"Low difficulty share: { response ['error' ]['message' ]} " )
150197 return
151198
152- if __name__ == "__main__" :
153- if pool_address .startswith ("stratum+tcp://" ):
154- pool_address = pool_address [len ("stratum+tcp://" ):]
155-
156- while True :
157- try :
158- sock = connect_to_pool (pool_address , pool_port )
199+ def mine_with_rpc ():
200+ try :
201+ conn , headers = connect_to_bitcoin_rpc (rpc_user , rpc_password , pool_address , rpc_port )
202+
203+ while True :
204+ template = send_rpc_request (conn , headers , "getblocktemplate" , [{"rules" : ["segwit" ]}])
205+ if 'error' in template :
206+ print (f"Error getting block template: { template ['error' ]} " )
207+ time .sleep (30 )
208+ continue
209+ print ("Got block template, mining..." )
210+ time .sleep (10 )
159211
160- extranonce = subscribe (sock )
161- extranonce1 , extranonce2_size = extranonce [1 ], extranonce [2 ]
162- authorize (sock , username , password )
163-
164- while True :
165- for response in receive_messages (sock ):
166- if response ['method' ] == 'mining.notify' :
167- job = response ['params' ]
168- result = mine (job , job [6 ], extranonce1 , extranonce2_size )
169- if result :
170- submit_solution (sock , * result )
171- except Exception as e :
172- print (f"An error occurred: { e } . Reconnecting..." )
173- time .sleep (5 )
212+ except Exception as e :
213+ print (f"RPC mining error: { e } " )
214+ finally :
215+ if 'conn' in locals ():
216+ conn .close ()
217+
218+ if __name__ == "__main__" :
219+ if connection_type == "stratum" :
220+ if pool_address .startswith ("stratum+tcp://" ):
221+ pool_address = pool_address [len ("stratum+tcp://" ):]
222+
223+ while True :
224+ try :
225+ sock = connect_to_pool (pool_address , pool_port )
226+
227+ extranonce = subscribe (sock )
228+ extranonce1 , extranonce2_size = extranonce [1 ], extranonce [2 ]
229+ authorize (sock , username , password )
230+
231+ while True :
232+ for response in receive_messages (sock ):
233+ if response ['method' ] == 'mining.notify' :
234+ job = response ['params' ]
235+ result = mine (job , job [6 ], extranonce1 , extranonce2_size )
236+ if result :
237+ submit_solution (sock , * result )
238+ except Exception as e :
239+ print (f"An error occurred: { e } . Reconnecting..." )
240+ time .sleep (5 )
241+
242+ elif connection_type == "rpc" :
243+ mine_with_rpc ()
244+ else :
245+ print (f"Invalid connection type: { connection_type } " )
0 commit comments