Simple Python CryptoCurrency mining client
A very simple pure Python implementation of a CryptoCurrency stratum CPU mining client. Currently supports scrypt (litecoin) and SHA256d (bitcoin).
python nightminer.py [-h] [-o URL] [-u USERNAME] [-p PASSWORD] [-O USERNAME:PASSWORD] [-a {scrypt,sha256d}] [-B] [-q] [-P] [-d] [-v]-o URL, --url= stratum mining server url -u USERNAME, --user= username for mining server -p PASSWORD, --pass= password for mining server -O USER:PASS, --userpass= username:password pair for mining server
-a, --algo hashing algorithm to use for proof of work (scrypt, sha256d)
-B, --background run in the background as a daemon
-q, --quiet suppress non-errors -P, --dump-protocol show all JSON-RPC chatter -d, --debug show extra debug information
-h, --help show the help message and exit -v, --version show program's version number and exit
Example: python nightminer.py -o stratum+tcp://foobar.com:3333 -u user -p passwd
The API can be used by anyone wishing to create their own modified miner to learn more about the protocol, test their own pool or experiment with new algorithms.
import nightminer
By default, the fastest detected library will be used; but if you wish to force a specific implementation:
nightminer.set_scrypt_library(library = nightminer.SCRYPT_LIBRARY_AUTO) print nightminer.SCRYPT_LIBRARY
After connecting to a stratum server, there is a small level of handshaking and then occasional messages to maintain state. The
Subscriptionclass manages this subscription state with the server.
Properties: *
id- The subscription ID *
worker_name- The name of the authenticated worker *
difficulty,
target- The result of the proof of work must be less than
target*
extranounce1- The extranounce1 *
extranounce2_size- The size of the binary extranounce2 (in bytes)
setsubscription(subscriptionid, extranounce1, extranounce2_size) Sets up the subscription details. Reply from the server to
mining.subscribe.
set_difficulty(difficulty) Sets the current difficulty. Sent from the server as a
mining.set_difficultymessage.
setworkername(worker_name) Sets the worker's name after the server has authenticated the username/password. Reply from the server to
mining.authorize.
createjob(jobid, prevhash, coinb1, coinb2, merkle_branches, version, nbits, ntime) Creates a new job. Sent from the server as a
mining.notifymessage.
When the server has a new job to work on it sends a
mining.notiffymessage. The
Jobclass manages all the paameters required to perform work and performs the actual mining.
Properties: *
id- The job ID *
prevhash- The previous hash *
coinb,
coinb2- The coinbase prefix and suffix *
merkle_branches- The Merkle branches *
version- The version *
nbits,
ntime- The network bits and network time *
target,
extranounce,
extranounce2_size- See
Subscriptionclass above *
hashrate- The rate this miner has been hashing at
merklerootbin(extranounce2_bin) Calculate the Merkle root, as a binary string.
mine(nouncestart = 0, nouncestride = 1) Iterates over all solutions for this job. This will run for an extrememly long time, likely far longer than ntime would be valid, so you will likely call
stop()at some point and start on a new job.
stop() Causes the
mine()method to finish immediately for any thread inside.
This is a sub-class of
SimpleJsonRpcClientwhich connects to the stratum server and processes work requests from the server updating a
Subscriptionobject.
Properties: *
url- The stratum server URL *
username,
password- The provided username and password
serve_forever() Connect to the server, handshake and block forever while handling work from the server.
miner = Miner('stratum+tcp://foobar.com:3333', 'username', 'password') miner.server_forever()
For this example, we will create a CryptoCoin based on MD5.
import hashlibCreate the Subscription object (proof-of-work should be 32 bytes long)
class SubscriptionMd5(nightminer.Subscription): def ProofOfWork(self, header): return hashlib.md5(header).digest() + ('0' * 16)
If you wish to manually find a few valid shares: ```python
subs = SubscriptionMd5() subs.setsubscription('mysubsid', '00000000', 4) subs.setdifficulty(1.0 / (2 ** 16)) subs.setworkername('myfakeworker')
job = subs.createjob('myjob', ('0' * 64), ('0' * 118), ('0' * 110), [ ], '00000002', 'deadbeef', '01234567')
sharecount = 0 for validshare in job.mine(): print "Found a valid share:", validshare sharecount += 1 if share_count == 5: break
print "Hashrate:", job.hashrate ```
Or if you already have a server ready to go with your algorithm: ```python
SubscriptionByAlgorithm['my_algo'] = SubscriptionMd5
miner = Miner('stratum+tcp://localhost:3333', 'username', 'password', 'myalgo') miner.serverforever() ```
Why would you do this? I was trying to tinker around with Litecoin, but found it difficult to find a simple, complete example of how to decode the endianness of the provided parameters and build the block header. So, the obvious next step is to create a full client to experiment with.
Why is this so slow? It is written in Python. It is not meant to be fast, more of a reference solution or something that can be easily hacked into to test your own pool.
On my MacBook Air, with one thread I get around 3,000 hashes/s using the
ltc_scryptlibary but less than 2 hashes/s using the built-in pure Python scrypt.
What is this ltc_scrypt you speak of? It is a Python C-binding for a C implementation of scrypt found in p2pool (https://github.com/forrestv/p2pool). To add to your own system:
> # Download the source > curl -L https://github.com/forrestv/p2pool/archive/13.4.tar.gz > p2pool-13.4.tar.gz> # Untar > tar -xzf p2pool-13.4.tar.gz
> # Build and install > cd p2pool-13.4/litecoin_scrypt/ > python setup.py build > sudo python setup.py install
After this is installed, this miner will be about 2,000 times faster.
Why am I am only getting rejected shares? Make sure you are using the correct algoithm, that means
--algo=scrypt(the default) for Litecoin or
--algo=sha256dfor Bitcoin.
How do I get a question I have added? E-mail me at [email protected] with any questions, suggestions, comments, et cetera.
Can I give you my money? Umm... Ok? :-)
Bitcoin -
1LNdGsYtZXWeiKjGba7T997qvzrWqLXLmaLitecoin -
LXths3ddkRtuFqFAU7sonQ678bSGkXzh5QNamecoin -
N6JLCggCyYcpcUq3ydJtLxv67eEJg4Ntk2