-
Notifications
You must be signed in to change notification settings - Fork 264
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4a303d0
commit 2e33c11
Showing
30 changed files
with
2,566 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,29 @@ | ||
Ethereum stratum proxy - for ethereum-pools using stratum protocol RPCv2 | ||
|
||
Copyright (C) 2015 Atrides <[email protected]> http://DwarfPool.com/eth | ||
|
||
# Stratum proxy | ||
|
||
Copyright (C) slush0 | ||
https://github.com/slush0/stratum-mining-proxy | ||
|
||
# Stratum protocol | ||
https://github.com/slush0/stratum | ||
|
||
Copyright (C) 2012 Marek Palatinus <[email protected]> | ||
|
||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU Affero General Public License as | ||
published by the Free Software Foundation, either version 3 of the | ||
License, or any later version. | ||
|
||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU Affero General Public License for more details. | ||
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
GNU GENERAL PUBLIC LICENSE | ||
Version 2, June 1991 | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,108 @@ | ||
# eth-proxy | ||
Stratum proxy for Ethereum | ||
#Description | ||
|
||
This is Stratum Proxy for Ethereum-pools (RPCv2) using asynchronous networking written in Python Twisted. | ||
Originally developed for DwarfPool http://dwarfpool.com/eth | ||
|
||
**NOTE:** This fork is still in development. Some features may be broken. Please report any broken features or issues. | ||
|
||
|
||
#Features | ||
|
||
* Additional 10%~20% increase of earning compared to standard pools | ||
* ETH stratum proxy | ||
* Only one connection to the pool | ||
* Workers get new jobs immediately | ||
* Submit of shares without network delay, it's like solo-mining but with benefits of professional pool | ||
* Central Wallet configuration, miners doesn't need wallet as username | ||
* Support monitoring via email | ||
* Bypass worker_id for detailed statistic and per rig monitoring | ||
|
||
|
||
#How it works | ||
|
||
Pool A <---+ +-------------+ Rig1 / PC1 | ||
(Active) | | | ||
| +-------------+ Rig2 / PC2 | ||
| | | ||
Pool B <---+-----StratumProxy <-----+-------------+ Rig3 / PC3 | ||
(FailOver) | | ||
+-------------+ Rig4 / PC4 | ||
| | ||
+-------------+ Leaserigs | ||
|
||
|
||
#ToDo | ||
|
||
* Automatically failover via proxy | ||
* Create for Windows users compiled .exe file | ||
* pass submitHashrate to pool | ||
|
||
|
||
#Configuration | ||
|
||
* all configs in file config.py | ||
|
||
|
||
#Command line to miner start, recommended farm-recheck to use with stratum-proxy is 200 | ||
|
||
* ./ethminer --farm-recheck 200 -G -F http://127.0.0.1:8080/rig1 | ||
|
||
|
||
#Donations | ||
|
||
* ETH: 0xb7302f5988cd483db920069a5c88f049a3707e2f | ||
|
||
|
||
#Requirements | ||
|
||
eth-proxy is built in python. I have been testing it with 2.7.3, but it should work with other versions. The requirements for running the software are below. | ||
|
||
* Python 2.7+ | ||
* python-twisted | ||
|
||
|
||
#Installation and start | ||
|
||
* [Linux] | ||
1) install twisted | ||
apt-get install python-twisted | ||
2) start proxy with | ||
python ./eth-proxy.py | ||
|
||
* [Windows] | ||
1) Download Python Version 2.7.10 for Windows | ||
https://www.python.org/downloads/ | ||
|
||
2) Modify PATH variable (how-to http://www.java.com/en/download/help/path.xml) and add | ||
C:\Python27;C:\Python27\Scripts; | ||
|
||
3) Install python setuptools | ||
https://pypi.python.org/pypi/setuptools/#windows-7-or-graphical-install | ||
|
||
4) Install Python-Twisted | ||
https://pypi.python.org/pypi/Twisted/15.4.0 | ||
File Twisted-15.4.0.win32-py2.7.msi (32bit) or Twisted-15.4.0.win-amd64-py2.7.msi (64bit) | ||
|
||
5) Install zope.interface, in console run: | ||
easy_install -U zope.interface | ||
|
||
6) Install PyWin32 v2.7 | ||
pywin32-219.win32-py2.7.exe or pywin32-219.win-amd64-py2.7.exe | ||
http://sourceforge.net/projects/pywin32/files/pywin32/ | ||
|
||
7) Download eth-proxy. Extract eth-proxy.zip. Change settings in config.py and start with command: | ||
python xmr-proxy.py | ||
|
||
|
||
#Contact | ||
|
||
* I am available via [email protected] | ||
|
||
#Credits | ||
|
||
* Original version by Slush0 (original stratum code) | ||
* More Features added by GeneralFault, Wadee Womersley and Moopless | ||
|
||
#License | ||
|
||
* This software is provides AS-IS without any warranties of any kind. Please use at your own risk. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
### | ||
# Command line for miners: | ||
# | ||
# ethminer.exe -G -F http://HOST:PORT/ | ||
# ethminer.exe -G -F http://HOST:PORT/rig1 | ||
# | ||
# ethminer.exe -G -F http://127.0.0.1:8080/ | ||
# ethminer.exe -G -F http://192.168.0.33:8080/rig1 | ||
# | ||
# You can submit shares without workername or | ||
# You can provide workername: | ||
# - with url like "/rig1" | ||
# - or use automatically numbering(integer) based on IP of miner | ||
### | ||
|
||
# Host and port for your workers | ||
HOST = "0.0.0.0" | ||
PORT = 8080 | ||
|
||
# Coin address where money goes | ||
WALLET = "0x2a65aca4d5fc5b5c859090a6c34d164135398226" | ||
|
||
# It's useful for individually monitoring and statistic | ||
ENABLE_WORKER_ID = True | ||
|
||
# On DwarfPool you have option to monitor your workers via email. | ||
# If WORKER_ID is enabled, you can monitor every worker/rig separately. | ||
MONITORING = False | ||
MONITORING_EMAIL = "[email protected]" | ||
|
||
# Main pool | ||
POOL_HOST = "eth-ru.dwarfpool.com" | ||
POOL_PORT = 8008 | ||
|
||
# Failover pool. CURRENTLY DOESN'T WORK! | ||
POOL_FAILOVER_ENABLE = False | ||
POOL_HOST_FAILOVER = "eth-eu.dwarfpool.com" | ||
POOL_PORT_FAILOVER = 8008 | ||
|
||
# Logging | ||
LOG_TO_FILE = True | ||
|
||
# Enable debug | ||
DEBUG = False | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
#!/usr/bin/env python | ||
# -*- coding:utf-8 -*- | ||
|
||
import time | ||
import os | ||
import socket | ||
|
||
from stratum import settings | ||
import stratum.logger | ||
log = stratum.logger.get_logger('proxy') | ||
|
||
if __name__ == '__main__': | ||
if len(settings.WALLET)!=42 and len(settings.WALLET)!=40: | ||
log.error("Wrong WALLET!") | ||
quit() | ||
settings.CUSTOM_EMAIL = settings.MONITORING_EMAIL if settings.MONITORING_EMAIL and settings.MONITORING else "" | ||
|
||
from twisted.internet import reactor, defer, protocol | ||
from twisted.internet import reactor as reactor2 | ||
from stratum.socket_transport import SocketTransportFactory, SocketTransportClientFactory | ||
from stratum.services import ServiceEventHandler | ||
from twisted.web.server import Site | ||
from stratum.custom_exceptions import TransportException | ||
|
||
from mining_libs import getwork_listener | ||
from mining_libs import client_service | ||
from mining_libs import jobs | ||
from mining_libs import version | ||
from mining_libs.jobs import Job | ||
|
||
def on_shutdown(f): | ||
'''Clean environment properly''' | ||
log.info("Shutting down proxy...") | ||
if os.path.isfile('eth-proxy.pid'): | ||
os.remove('eth-proxy.pid') | ||
f.is_reconnecting = False # Don't let stratum factory to reconnect again | ||
|
||
# Support main connection | ||
@defer.inlineCallbacks | ||
def ping(f): | ||
if not f.is_reconnecting: | ||
return | ||
try: | ||
yield (f.rpc('eth_getWork', [], '')) | ||
reactor.callLater(60, ping, f) | ||
except Exception: | ||
pass | ||
|
||
@defer.inlineCallbacks | ||
def on_connect(f): | ||
'''Callback when proxy get connected to the pool''' | ||
log.info("Connected to Stratum pool at %s:%d" % f.main_host) | ||
#reactor.callLater(30, f.client.transport.loseConnection) | ||
|
||
# Hook to on_connect again | ||
f.on_connect.addCallback(on_connect) | ||
|
||
# Get first job and user_id | ||
initial_job = (yield f.rpc('eth_submitLogin', [settings.WALLET, settings.CUSTOM_EMAIL], 'Proxy_'+version.VERSION)) | ||
|
||
reactor.callLater(0, ping, f) | ||
|
||
defer.returnValue(f) | ||
|
||
def on_disconnect(f): | ||
'''Callback when proxy get disconnected from the pool''' | ||
log.info("Disconnected from Stratum pool at %s:%d" % f.main_host) | ||
f.on_disconnect.addCallback(on_disconnect) | ||
|
||
# Prepare to failover, currently works very bad | ||
#if f.main_host==(settings.POOL_HOST, settings.POOL_PORT): | ||
# main() | ||
#else: | ||
# f.is_reconnecting = False | ||
#return f | ||
|
||
@defer.inlineCallbacks | ||
def main(): | ||
reactor.disconnectAll() | ||
failover = False | ||
if settings.POOL_FAILOVER_ENABLE: | ||
failover = settings.failover_pool | ||
settings.failover_pool = not settings.failover_pool | ||
|
||
pool_host = settings.POOL_HOST | ||
pool_port = settings.POOL_PORT | ||
if failover and settings.POOL_FAILOVER_ENABLE: | ||
pool_host = settings.POOL_HOST_FAILOVER | ||
pool_port = settings.POOL_PORT_FAILOVER | ||
|
||
log.warning("Ethereum Stratum proxy version: %s" % version.VERSION) | ||
log.warning("Trying to connect to Stratum pool at %s:%d" % (pool_host, pool_port)) | ||
|
||
# Connect to Stratum pool, main monitoring connection | ||
f = SocketTransportClientFactory(pool_host, pool_port, | ||
debug=settings.DEBUG, proxy=None, | ||
event_handler=client_service.ClientMiningService) | ||
|
||
job_registry = jobs.JobRegistry(f) | ||
client_service.ClientMiningService.job_registry = job_registry | ||
client_service.ClientMiningService.reset_timeout() | ||
|
||
f.on_connect.addCallback(on_connect) | ||
f.on_disconnect.addCallback(on_disconnect) | ||
# Cleanup properly on shutdown | ||
reactor.addSystemEventTrigger('before', 'shutdown', on_shutdown, f) | ||
|
||
# Block until proxy connect to the pool | ||
try: | ||
yield f.on_connect | ||
except TransportException: | ||
log.warning("First pool server must be online first time to start failover") | ||
return | ||
|
||
conn = reactor.listenTCP(settings.PORT, Site(getwork_listener.Root(job_registry, settings.ENABLE_WORKER_ID)), interface=settings.HOST) | ||
|
||
try: | ||
conn.socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) # Enable keepalive packets | ||
conn.socket.setsockopt(socket.SOL_TCP, socket.TCP_KEEPIDLE, 60) # Seconds before sending keepalive probes | ||
conn.socket.setsockopt(socket.SOL_TCP, socket.TCP_KEEPINTVL, 1) # Interval in seconds between keepalive probes | ||
conn.socket.setsockopt(socket.SOL_TCP, socket.TCP_KEEPCNT, 5) # Failed keepalive probles before declaring other end dead | ||
except: | ||
pass # Some socket features are not available on all platforms (you can guess which one) | ||
|
||
log.warning("-----------------------------------------------------------------------") | ||
if settings.HOST == '0.0.0.0': | ||
log.warning("PROXY IS LISTENING ON ALL IPs ON PORT %d" % settings.PORT) | ||
else: | ||
log.warning("LISTENING FOR MINERS ON http://%s:%d" % (settings.HOST, settings.PORT)) | ||
log.warning("-----------------------------------------------------------------------") | ||
log.warning("Wallet: %s" % settings.WALLET) | ||
log.warning("Worker ID enabled: %s" % settings.ENABLE_WORKER_ID) | ||
if settings.MONITORING: | ||
log.warning("Email monitoring on %s" % settings.MONITORING_EMAIL) | ||
else: | ||
log.warning("Email monitoring diasbled") | ||
#log.warning("Failover enabled: %" % settings.POOL_FAILOVER_ENABLE) | ||
log.warning("-----------------------------------------------------------------------") | ||
|
||
if __name__ == '__main__': | ||
fp = file("eth-proxy.pid", 'w') | ||
fp.write(str(os.getpid())) | ||
fp.close() | ||
settings.failover_pool = False | ||
main() | ||
reactor.run() |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
from twisted.internet import reactor | ||
|
||
from stratum.event_handler import GenericEventHandler | ||
from jobs import Job | ||
import version as _version | ||
|
||
import stratum.logger | ||
log = stratum.logger.get_logger('proxy') | ||
|
||
class ClientMiningService(GenericEventHandler): | ||
job_registry = None # Reference to JobRegistry instance | ||
timeout = None # Reference to IReactorTime object | ||
|
||
@classmethod | ||
def reset_timeout(cls): | ||
if cls.timeout != None: | ||
if not cls.timeout.called: | ||
cls.timeout.cancel() | ||
cls.timeout = None | ||
|
||
cls.timeout = reactor.callLater(960, cls.on_timeout) | ||
|
||
@classmethod | ||
def on_timeout(cls): | ||
''' | ||
Try to reconnect to the pool after 16 minutes of no activity on the connection. | ||
It will also drop all Stratum connections to sub-miners | ||
to indicate connection issues. | ||
''' | ||
log.error("Connection to upstream pool timed out") | ||
cls.reset_timeout() | ||
cls.job_registry.f.reconnect() | ||
|
||
def handle_event(self, method, params, connection_ref): | ||
'''Handle RPC calls and notifications from the pool''' | ||
# Yay, we received something from the pool, | ||
# let's restart the timeout. | ||
self.reset_timeout() | ||
|
||
if method == 'eth_getWork': | ||
'''Proxy just received information about new mining job''' | ||
# Broadcast to getwork clients | ||
job = Job.build_from_pool(params) | ||
if stratum.logger.settings.DEBUG: | ||
log.debug("NEW_JOB %s" % params) | ||
else: | ||
log.info("NEW_JOB") | ||
self.job_registry.replace_job(job) | ||
|
||
else: | ||
'''Pool just asked us for something which we don't support...''' | ||
log.error("Unhandled method %s with params %s" % (method, params)) |
Oops, something went wrong.