Bitcoin Forum
April 17, 2014, 01:09:08 AM *
News: ♦♦ A bug in OpenSSL, used by Bitcoin-Qt/Bitcoin Core, could allow your bitcoins to be stolen. Immediately updating Bitcoin Core to 0.9.1 is required in some cases, especially if you're using 0.9.0. Download. More info.
The same bug also affected the forum. Changing your forum password is recommended.
 
   Home   Help Search Donate Login Register  
Pages: 1 [2] 3  All
  Print  
Author Topic: New pure-python CPU miner, for fun and testing  (Read 15040 times)
kseistrup
Sr. Member
****
Offline Offline

Activity: 462


corruptisima re publica plurimae leges


View Profile WWW

Ignore
February 19, 2011, 09:43:45 AM
 #21

Oh, and one more thing:

In the work loop, the line “hashes_done += 1” is effectively useless since nonce is already running from 0 to MAX_NONCE.  So at the end of the loop — either because a winning solution has been found, or because MAX_NONCE has been reached — hashes_done equals nonce+1.  Dropping the “hashes_done += 1” line gives a few extra khash/sec since this line was executed so many times.

Cheers,

Klaus Seistrup | BM-BbvXWtfhr5nENu4TQtnxif16SUCdNKAF
BTC: 1KLAUScYZ4LMRciPbDyENXU5H5kg1kossP
XRP: r4X2aBGRhRoQvwQ4P4WibwKB2Q9biVN4Hu
1397696948
Hero Member
*
Offline Offline

Posts: 1397696948

View Profile Personal Message (Offline)

Ignore
1397696948
Reply with quote  #2

1397696948
Report to moderator
1397696948
Hero Member
*
Offline Offline

Posts: 1397696948

View Profile Personal Message (Offline)

Ignore
1397696948
Reply with quote  #2

1397696948
Report to moderator
1397696948
Hero Member
*
Offline Offline

Posts: 1397696948

View Profile Personal Message (Offline)

Ignore
1397696948
Reply with quote  #2

1397696948
Report to moderator
      THE ONLY DICE GAME WITH ACTUAL ROLLING DICE BetCoin™ Dice
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction. Advertise here.
1397696948
Hero Member
*
Offline Offline

Posts: 1397696948

View Profile Personal Message (Offline)

Ignore
1397696948
Reply with quote  #2

1397696948
Report to moderator
1397696948
Hero Member
*
Offline Offline

Posts: 1397696948

View Profile Personal Message (Offline)

Ignore
1397696948
Reply with quote  #2

1397696948
Report to moderator
1397696948
Hero Member
*
Offline Offline

Posts: 1397696948

View Profile Personal Message (Offline)

Ignore
1397696948
Reply with quote  #2

1397696948
Report to moderator
1397696948
Hero Member
*
Offline Offline

Posts: 1397696948

View Profile Personal Message (Offline)

Ignore
1397696948
Reply with quote  #2

1397696948
Report to moderator
kseistrup
Sr. Member
****
Offline Offline

Activity: 462


corruptisima re publica plurimae leges


View Profile WWW

Ignore
February 19, 2011, 10:10:33 AM
 #22

I wonder if this is a bug:

Code:
        # hash final 4b, the nonce value
        hash1_o = hash1_precalc_o
        hash1_o.update(nonce_bin)
        hash1 = hash1_o.digest()

Do I interpret your meaning right when I say that the code — for each value of nonce — intends to calculate the SHA256 digest of the precalculated value (intended to stay constant throughout the loop) updated with the nonce?  If so, that is not what the code does.  Please see this simplified example:

Code:
>>> from hashlib import sha256
>>> pre = sha256('abc')
>>> post = pre
>>> post.update('xyz')
>>> pre.digest() == post.digest()
True
>>>

So pre and post (like hash1_precalc_o and hash1_o) both points to the same object, and so I guess we should really write:

Code:
        # hash final 4b, the nonce value
        hash1_o = hashlib.sha256(blk_hdr + nonce_bin)
        hash1 = hash1_o.digest()

or even

Code:
        # hash final 4b, the nonce value
        hash1 = hashlib.sha256(blk_hdr + nonce_bin).digest()

Or did I misunderstand the whole concept?

Cheers,

Klaus Seistrup | BM-BbvXWtfhr5nENu4TQtnxif16SUCdNKAF
BTC: 1KLAUScYZ4LMRciPbDyENXU5H5kg1kossP
XRP: r4X2aBGRhRoQvwQ4P4WibwKB2Q9biVN4Hu
jgarzik
Staff
Hero Member
*****
Offline Offline

Activity: 1260


View Profile

Ignore
February 19, 2011, 05:44:36 PM
 #23

Do I interpret your meaning right when I say that the code — for each value of nonce — intends to calculate the SHA256 digest of the precalculated value (intended to stay constant throughout the loop) updated with the nonce?  If so, that is not what the code does.  Please see this simplified example:

Well, that is disappointing.  If true, yes, that is a bug.  Updated.

Jeff Garzik, bitcoin core dev team and BitPay engineer; opinions are my own, not my employer.
Donations / tip jar: 1BrufViLKnSWtuWGkryPsKsxonV2NQ7Tcj
kseistrup
Sr. Member
****
Offline Offline

Activity: 462


corruptisima re publica plurimae leges


View Profile WWW

Ignore
February 19, 2011, 05:52:54 PM
 #24

Updated.
Do you happen to have a git repository of the code?

Cheers,

Klaus Seistrup | BM-BbvXWtfhr5nENu4TQtnxif16SUCdNKAF
BTC: 1KLAUScYZ4LMRciPbDyENXU5H5kg1kossP
XRP: r4X2aBGRhRoQvwQ4P4WibwKB2Q9biVN4Hu
jgarzik
Staff
Hero Member
*****
Offline Offline

Activity: 1260


View Profile

Ignore
February 19, 2011, 05:54:04 PM
 #25

Updated.
Do you happen to have a git repository of the code?

No, just the URL.

Jeff Garzik, bitcoin core dev team and BitPay engineer; opinions are my own, not my employer.
Donations / tip jar: 1BrufViLKnSWtuWGkryPsKsxonV2NQ7Tcj
kseistrup
Sr. Member
****
Offline Offline

Activity: 462


corruptisima re publica plurimae leges


View Profile WWW

Ignore
February 19, 2011, 06:26:01 PM
 #26

No, just the URL.
Okay, no pull-request for you, then.  Wink

Please consider the following patch for inclusion:

Code:
--- pyminer.py 2011-02-19 19:05:29.794843964 +0100
+++ pyminer-opt.py 2011-02-19 19:20:06.136093826 +0100
@@ -113,28 +113,22 @@
  targetbin_str = targetbin.encode('hex')
  target = long(targetbin_str, 16)
 
- hashes_done = 1
- for nonce in range(MAX_NONCE):
+ for nonce in xrange(MAX_NONCE):
 
  # encode 32-bit nonce value
  nonce_bin = struct.pack("<I", nonce)
 
  # hash final 4b, the nonce value
- hash1_o = hashlib.sha256()
- hash1_o.update(blk_hdr)
+ hash1_o = hashlib.sha256(blk_hdr)
  hash1_o.update(nonce_bin)
  hash1 = hash1_o.digest()
 
  # sha256 hash of sha256 hash
- hash_o = hashlib.sha256()
- hash_o.update(hash1)
+ hash_o = hashlib.sha256(hash1)
  hash = hash_o.digest()
 
- hashes_done += 1
-
  # quick test for winning solution: high 32 bits zero?
- H = struct.unpack('<I', hash[28:32])
- if H:
+ if hash[-4:] != '\0\0\0\0':
  continue
 
  # convert binary hash to 256-bit Python long
@@ -147,12 +141,12 @@
  # proof-of-work test:  hash < target
  if l < target:
  print time.asctime(), "PROOF-OF-WORK found: %064x" % (l,)
- return (hashes_done,
+ return (nonce+1,
  static_data[:76] + nonce_bin)
  else:
  print time.asctime(), "PROOF-OF-WORK false positive %064x" % (l,)
 
- return (hashes_done, None)
+ return (nonce+1, None)
 
  def iterate(self, rpc):
  work = rpc.getwork()

The patch eliminates 2 calls to hashlib.sha256(), 1 call to struct.unpack() and 1 one variable increment per work loop.

Cheers,

Klaus Seistrup | BM-BbvXWtfhr5nENu4TQtnxif16SUCdNKAF
BTC: 1KLAUScYZ4LMRciPbDyENXU5H5kg1kossP
XRP: r4X2aBGRhRoQvwQ4P4WibwKB2Q9biVN4Hu
mail2345
Newbie
*
Offline Offline

Activity: 16


View Profile

Ignore
February 19, 2011, 06:54:30 PM
 #27

Psyco should speed things up.

BTC Address: 12TJbeJ2aCzCppJ6m1yYoPUdp9EHWRTQNv
kseistrup
Sr. Member
****
Offline Offline

Activity: 462


corruptisima re publica plurimae leges


View Profile WWW

Ignore
February 19, 2011, 07:26:32 PM
 #28

Psyco should speed things up.
Psyco only runs on “obsolete” versions of Python (and it doesn't work on any 64-bit systems at all).

Cheers,

Klaus Seistrup | BM-BbvXWtfhr5nENu4TQtnxif16SUCdNKAF
BTC: 1KLAUScYZ4LMRciPbDyENXU5H5kg1kossP
XRP: r4X2aBGRhRoQvwQ4P4WibwKB2Q9biVN4Hu
bitjet
Hero Member
*****
Offline Offline

Activity: 556


View Profile

Ignore
February 19, 2011, 07:43:22 PM
 #29

Are you guys getting near triple efficiency with this vs over poclbm?
Kiv
Full Member
***
Offline Offline

Activity: 162



View Profile

Ignore
February 27, 2011, 07:53:42 PM
 #30

I'm trying to run this and getting an exception:

Code:
Process Process-1:
Traceback (most recent call last):
  File "C:\Python26\lib\multiprocessing\process.py", line 232, in _bootstrap
    self.run()
  File "C:\Python26\lib\multiprocessing\process.py", line 88, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Users\Chris\workspace\pyminer\pyminer.py", line 197, in miner_thread
    miner.loop()
  File "C:\Users\Chris\workspace\pyminer\pyminer.py", line 187, in loop
    rpc = BitcoinRPC(settings['host'], settings['port'],
KeyError: 'host'
1 mining threads started
Sun Feb 27 15:51:18 2011 Miner Starts - 127.0.0.1:8332
Sun Feb 27 15:51:18 2011 Miner Stops - 127.0.0.1:8332

It seems that the settings dictionary is empty, because when we're using separate processes the children don't have access to the parent's variables. Probably the settings should be passed in as constructor arguments. I might put this up on GitHub and hack on it a bit if you don't mind Smiley

GUIMiner - get started easily mining Bitcoins on your GPU or CPU
Donate to support work on GUIMiner: 1MDDh2h4cAZDafgc94mr9q95dhRYcJbNQo
or YouTipIt
Kiv
Full Member
***
Offline Offline

Activity: 162



View Profile

Ignore
February 27, 2011, 07:57:18 PM
 #31

Are you guys getting near triple efficiency with this vs over poclbm?

Definitely not, I get about 900 KHash per core on poclbm and only 182 KHash per core on pure-python.

GUIMiner - get started easily mining Bitcoins on your GPU or CPU
Donate to support work on GUIMiner: 1MDDh2h4cAZDafgc94mr9q95dhRYcJbNQo
or YouTipIt
kseistrup
Sr. Member
****
Offline Offline

Activity: 462


corruptisima re publica plurimae leges


View Profile WWW

Ignore
February 27, 2011, 07:57:49 PM
 #32

Code:
  File "C:\Users\Chris\workspace\pyminer\pyminer.py", line 187, in loop
    rpc = BitcoinRPC(settings['host'], settings['port'],
KeyError: 'host'
Pyminer takes as its single argument the name of the config file.  Please see message #10 in this thread.

Cheers,

Klaus Seistrup | BM-BbvXWtfhr5nENu4TQtnxif16SUCdNKAF
BTC: 1KLAUScYZ4LMRciPbDyENXU5H5kg1kossP
XRP: r4X2aBGRhRoQvwQ4P4WibwKB2Q9biVN4Hu
Kiv
Full Member
***
Offline Offline

Activity: 162



View Profile

Ignore
February 27, 2011, 08:03:21 PM
 #33

Thank you, but I did supply the argument. In fact the program will not start without the config file. My config file is the right format as well and has "host=127.0.0.1" in it.

I suspect that the program worked fine at one point and I have a more recent version with a bug in it.


Code:
  File "C:\Users\Chris\workspace\pyminer\pyminer.py", line 187, in loop
    rpc = BitcoinRPC(settings['host'], settings['port'],
KeyError: 'host'
Pyminer takes as its single argument the name of the config file.  Please see message #10 in this thread.

Cheers,

GUIMiner - get started easily mining Bitcoins on your GPU or CPU
Donate to support work on GUIMiner: 1MDDh2h4cAZDafgc94mr9q95dhRYcJbNQo
or YouTipIt
kseistrup
Sr. Member
****
Offline Offline

Activity: 462


corruptisima re publica plurimae leges


View Profile WWW

Ignore
February 27, 2011, 08:13:23 PM
 #34

I suspect that the program worked fine at one point and I have a more recent version with a bug in it.
The current version runs fine with this config file (username and password edited for obvious reasons):

Code:
host = mining.bitcoin.cz
port = 8332
rpcuser = myRPCUser
rpcpass = myRPCPass
logdir = /tmp
threads = 1
hashmeter = 1

Cheers,

Klaus Seistrup | BM-BbvXWtfhr5nENu4TQtnxif16SUCdNKAF
BTC: 1KLAUScYZ4LMRciPbDyENXU5H5kg1kossP
XRP: r4X2aBGRhRoQvwQ4P4WibwKB2Q9biVN4Hu
Kiv
Full Member
***
Offline Offline

Activity: 162



View Profile

Ignore
February 27, 2011, 08:26:13 PM
 #35

This is probably a Windows-only bug. From the multiprocessing docs:


Since Windows lacks os.fork() it has a few extra restrictions:
Global variables

Bear in mind that if code run in a child process tries to access a global variable, then the value it sees (if any) may not be the same as the value in the parent process at the time that Process.start() was called.

If everyone else is running on Linux but I am running on Windows, this explains why it would work for others but not for me.

GUIMiner - get started easily mining Bitcoins on your GPU or CPU
Donate to support work on GUIMiner: 1MDDh2h4cAZDafgc94mr9q95dhRYcJbNQo
or YouTipIt
kseistrup
Sr. Member
****
Offline Offline

Activity: 462


corruptisima re publica plurimae leges


View Profile WWW

Ignore
February 27, 2011, 08:35:00 PM
 #36

If everyone else is running on Linux but I am running on Windows, this explains why it would work for others but not for me.
It sure does.

Cheers,

Klaus Seistrup | BM-BbvXWtfhr5nENu4TQtnxif16SUCdNKAF
BTC: 1KLAUScYZ4LMRciPbDyENXU5H5kg1kossP
XRP: r4X2aBGRhRoQvwQ4P4WibwKB2Q9biVN4Hu
rasputin
Newbie
*
Offline Offline

Activity: 15


View Profile

Ignore
March 23, 2011, 12:11:25 PM
 #37

I wonder if this is a bug:

Code:
       # hash final 4b, the nonce value
        hash1_o = hash1_precalc_o
        hash1_o.update(nonce_bin)
        hash1 = hash1_o.digest()

Do I interpret your meaning right when I say that the code — for each value of nonce — intends to calculate the SHA256 digest of the precalculated value (intended to stay constant throughout the loop) updated with the nonce?  If so, that is not what the code does.  Please see this simplified example:

Code:
>>> from hashlib import sha256
>>> pre = sha256('abc')
>>> post = pre
>>> post.update('xyz')
>>> pre.digest() == post.digest()
True
>>>

So pre and post (like hash1_precalc_o and hash1_o) both points to the same object

Instead of assignment, you'd use hashlib's copy() method to duplicate the hash state.

This code should work as intended:
Code:
# hash final 4b, the nonce value
hash1_o = hash1_precalc_o.copy()
hash1_o.update(nonce_bin)
hash1 = hash1_o.digest()
rasputin
Newbie
*
Offline Offline

Activity: 15


View Profile

Ignore
March 23, 2011, 12:29:07 PM
 #38

I'm not sure you caught my point.
You're right, I didn't catch your point.  I have to chew on that, though.  What we need is a binary buffer with the right endianness, not a python long integer, right?

No, we really do need a 256-integer, because that is the fundamental proof-of-work test in the bitcoin system, comparing two 256-bit integers:

     hash < target

You may just as well compare the two arrays of binary data:
Code:
>>> a = "aaaa".decode('hex')
>>> b = "bbbb".decode('hex')
>>> a > b
False
>>> b > a
True

Got to love high level languages.

Considered putting this on github as well, btw? Being smaller and higher level, I find it a lot easier to grasp than the C miner. Too bad about all the byte order manipulation, but I guess that can't be helped.
TehRainbowGuy
Newbie
*
Offline Offline

Activity: 8



View Profile

Ignore
April 04, 2011, 08:40:58 PM
 #39

I am loving the idea of this miner, much simpler than all of the others.

Just one question, any chance of a git repo?
jgarzik
Staff
Hero Member
*****
Offline Offline

Activity: 1260


View Profile

Ignore
April 04, 2011, 08:57:57 PM
 #40

Sure, here's a git repo:  https://github.com/jgarzik/pyminer

Jeff Garzik, bitcoin core dev team and BitPay engineer; opinions are my own, not my employer.
Donations / tip jar: 1BrufViLKnSWtuWGkryPsKsxonV2NQ7Tcj
Pages: 1 [2] 3  All
  Print  
 
Jump to:  

Sponsored by , a Bitcoin-accepting VPN.
Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!