Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Jan 16th, 2011  |  syntax: Python  |  size: 24.14 KB  |  hits: 78  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. diff --git a/BitcoinMiner.py b/BitcoinMiner.py
  2. index 728c0fa..638e11d 100644
  3. --- a/BitcoinMiner.py
  4. +++ b/BitcoinMiner.py
  5. @@ -1,11 +1,13 @@
  6.  import sys
  7.  import numpy as np
  8.  import pyopencl as cl
  9. +import socket
  10. +import bitcoin
  11.  
  12.  from struct import *
  13.  from Queue import Queue
  14.  from Queue import Empty
  15. -from threading import Thread
  16. +from threading import Thread, Event
  17.  from time import sleep, time
  18.  from datetime import datetime
  19.  from jsonrpc import ServiceProxy
  20. @@ -31,7 +33,7 @@ def if_else(condition, trueVal, falseVal):
  21.                 return falseVal
  22.  
  23.  class BitcoinMiner(Thread):
  24. -       def __init__(self, platform, context, host, user, password, port=8332, frames=60, rate=1, askrate=5, worksize=-1, vectors=False):
  25. +       def __init__(self, platform, context, device, host, user, password, port=8332, frames=60, rate=1, askrate=5, worksize=-1, vectors=False):
  26.                 Thread.__init__(self)
  27.                 (defines, self.rateDivisor) = if_else(vectors, ('-DVECTORS', 500), ('', 1000))
  28.  
  29. @@ -41,10 +43,13 @@ class BitcoinMiner(Thread):
  30.                 self.askrate = min(self.askrate, 10)
  31.                 self.worksize = int(worksize)
  32.                 self.frames = max(frames, 1)
  33. +               self.device = device
  34. +               self.hostname = socket.gethostname()
  35. +               self.logfile = "%s-%i.log" % (self.hostname, self.device)
  36. +               self.statusfile = "%s-%i.hashrate" % (self.hostname, self.device)
  37. +               self.sh = open(self.statusfile, "w")
  38. +               self.hashrate = None
  39.  
  40. -               if (self.context.devices[0].extensions.find('cl_amd_media_ops') != -1):
  41. -                       defines += ' -DBITALIGN'
  42. -                      
  43.                 kernelFile = open('BitcoinMiner.cl', 'r')
  44.                 self.miner = cl.Program(self.context, kernelFile.read()).build(defines)
  45.                 kernelFile.close()
  46. @@ -56,6 +61,11 @@ class BitcoinMiner(Thread):
  47.                 self.resultQueue = Queue()
  48.  
  49.                 self.bitcoin = ServiceProxy('http://%s:%s@%s:%s' % (user, password, host, port))
  50. +               self.node = Node(host, 8333)
  51. +
  52. +               self.node.newblock.set()
  53. +
  54. +               self.node.start()
  55.  
  56.         def say(self, format, args=()):
  57.                 sys.stdout.write('\r                                        \r' + format % args)
  58. @@ -63,6 +73,11 @@ class BitcoinMiner(Thread):
  59.  
  60.         def sayLine(self, format, args=()):
  61.                 self.say(format + '\n', args)
  62. +               formatted_line = format % args
  63. +               line = "%s-%i %s\n" % (self.hostname, self.device, formatted_line)
  64. +               fh = open(self.logfile, "a")
  65. +               fh.write(line)
  66. +               fh.close()
  67.  
  68.         def blockFound(self, hash, accepted):
  69.                 # designed to be overridden
  70. @@ -70,6 +85,7 @@ class BitcoinMiner(Thread):
  71.  
  72.         def getwork(self, data=None):
  73.                 try:
  74. +                       print "\ngetwork"
  75.                         if data:
  76.                                 return self.bitcoin.getwork(data)
  77.                         else:
  78. @@ -94,7 +110,8 @@ class BitcoinMiner(Thread):
  79.                                 except Empty:
  80.                                         pass
  81.  
  82. -                               if result or (time() - lastWork > self.askrate):
  83. +                               if result or self.node.newblock.isSet():
  84. +                                       self.node.newblock.clear()
  85.                                         self.workQueue.put(work)
  86.                                         lastWork = time()
  87.                                         work = None
  88. @@ -108,6 +125,12 @@ class BitcoinMiner(Thread):
  89.                         print '\nbye'
  90.                         sleep(1.1)
  91.  
  92. +       def dumpHashrate(self):
  93. +               self.sh.seek(0)
  94. +               self.sh.write(self.hashrate)
  95. +               self.sh.truncate(len(self.hashrate))
  96. +               self.sh.flush()
  97. +
  98.         def run(self):
  99.                 frame = float(1)/float(self.frames)
  100.                 window = frame/30
  101. @@ -124,6 +147,7 @@ class BitcoinMiner(Thread):
  102.                 output_buf = cl.Buffer(self.context, cl.mem_flags.WRITE_ONLY | cl.mem_flags.USE_HOST_PTR, hostbuf=output)
  103.  
  104.                 work = None
  105. +               hashstring = None
  106.                 while True:
  107.                         if (not work) or (not self.workQueue.empty()):
  108.                                 try:
  109. @@ -134,6 +158,8 @@ class BitcoinMiner(Thread):
  110.                                         if not work:
  111.                                                 continue
  112.                                         elif work == 'stop':
  113. +                                               self.node.stop()
  114. +                                               self.node.join()
  115.                                                 return
  116.                                         try:
  117.                                                 data   = np.array(unpack('IIIIIIIIIIIIIIII', work['data'][128:].decode('hex')), dtype=np.uint32)
  118. @@ -153,10 +179,14 @@ class BitcoinMiner(Thread):
  119.                                                                 state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7],
  120.                                                                 state2[1], state2[2], state2[3], state2[5], state2[6], state2[7],
  121.                                                                 target[6], target[7], pack('I', base), output_buf)
  122. +
  123.                         cl.enqueue_read_buffer(queue, output_buf, output)
  124.  
  125.                         if (time() - lastRate > self.rate):
  126. -                               self.say('%s khash/s', int((threadsRun / (time() - lastRate)) / self.rateDivisor))
  127. +                               hashrate = int((threadsRun / (time() - lastRate)) / self.rateDivisor)
  128. +                               self.hashrate = "%i khash/s" % hashrate
  129. +                               self.say(self.hashrate)
  130. +                               Thread(target = self.dumpHashrate).start()
  131.                                 threadsRun = 0
  132.                                 lastRate = time()
  133.  
  134. @@ -179,4 +209,17 @@ class BitcoinMiner(Thread):
  135.                                 result['hash'] = output[0]
  136.                                 self.resultQueue.put(result)
  137.                                 output[0] = 0
  138. -                               cl.enqueue_write_buffer(queue, output_buf, output)
  139. \ No newline at end of file
  140. +                               cl.enqueue_write_buffer(queue, output_buf, output)
  141. +
  142. +class Node(bitcoin.BitcoinNode):
  143. +       def __init__(self, dstaddr, dstport):
  144. +               self.__parent = super(Node, self)
  145. +               self.__parent.__init__(dstaddr, dstport)
  146. +               self.newblock = Event()
  147. +
  148. +       def do_tx(self, message):
  149. +               self.newblock.set()
  150. +
  151. +       def do_block(self, message):
  152. +               self.newblock.set()
  153. +
  154. diff --git a/bitcoin.py b/bitcoin.py
  155. new file mode 100755
  156. index 0000000..5ac1e44
  157. --- /dev/null
  158. +++ b/bitcoin.py
  159. @@ -0,0 +1,673 @@
  160. +#!/usr/bin/python
  161. +# Public Domain
  162. +
  163. +import struct
  164. +import threading
  165. +import select
  166. +import socket
  167. +import asyncore
  168. +import binascii
  169. +import time
  170. +import sys
  171. +import random
  172. +import cStringIO
  173. +from Crypto.Hash import SHA256
  174. +
  175. +MY_VERSION = 312
  176. +MY_SUBVERSION = ".4"
  177. +
  178. +Cs = 0
  179. +
  180. +def deser_string(f):
  181. +       nit = struct.unpack("<B", f.read(1))[0]
  182. +       if nit == 253:
  183. +               nit = struct.unpack("<H", f.read(2))[0]
  184. +       elif nit == 254:
  185. +               nit = struct.unpack("<I", f.read(4))[0]
  186. +       elif nit == 255:
  187. +               nit = struct.unpack("<Q", f.read(8))[0]
  188. +       return f.read(nit)
  189. +
  190. +def ser_string(s):
  191. +       if len(s) < 253:
  192. +               return chr(len(s)) + s
  193. +       elif len(s) < 0x10000:
  194. +               return chr(253) + struct.pack("<H", len(s)) + s
  195. +       elif len(s) < 0x100000000L:
  196. +               return chr(254) + struct.pack("<I", len(s)) + s
  197. +       return chr(255) + struct.pack("<Q", len(s)) + s
  198. +
  199. +def deser_uint256(f):
  200. +       r = 0L
  201. +       for i in xrange(8):
  202. +               t = struct.unpack("<I", f.read(4))[0]
  203. +               r += t << (i * 32)
  204. +       return r
  205. +
  206. +def ser_uint256(u):
  207. +       rs = ""
  208. +       for i in xrange(8):
  209. +               rs += struct.pack("<I", u & 0xFFFFFFFFL)
  210. +               u >>= 32
  211. +       return rs
  212. +
  213. +def uint256_from_str(s):
  214. +       r = 0L
  215. +       t = struct.unpack("<IIIIIIII", s[:32])
  216. +       for i in xrange(8):
  217. +               r += t[i] << (i * 32)
  218. +       return r
  219. +
  220. +def uint256_from_compact(c):
  221. +       nbytes = (c >> 24) & 0xFF
  222. +       v = (c & 0xFFFFFFL) << (8 * (nbytes - 3))
  223. +       return v
  224. +
  225. +def deser_vector(f, c):
  226. +       nit = struct.unpack("<B", f.read(1))[0]
  227. +       if nit == 253:
  228. +               nit = struct.unpack("<H", f.read(2))[0]
  229. +       elif nit == 254:
  230. +               nit = struct.unpack("<I", f.read(4))[0]
  231. +       elif nit == 255:
  232. +               nit = struct.unpack("<Q", f.read(8))[0]
  233. +       r = []
  234. +       for i in xrange(nit):
  235. +               t = c()
  236. +               t.deserialize(f)
  237. +               r.append(t)
  238. +       return r
  239. +
  240. +def ser_vector(l):
  241. +       r = ""
  242. +       if len(l) < 253:
  243. +               r = chr(len(l))
  244. +       elif len(l) < 0x10000:
  245. +               r = chr(253) + struct.pack("<H", len(l))
  246. +       elif len(l) < 0x100000000L:
  247. +               r = chr(254) + struct.pack("<I", len(l))
  248. +       else:
  249. +               r = chr(255) + struct.pack("<Q", len(l))
  250. +       for i in l:
  251. +               r += i.serialize()
  252. +       return r
  253. +
  254. +def deser_uint256_vector(f):
  255. +       nit = struct.unpack("<B", f.read(1))[0]
  256. +       if nit == 253:
  257. +               nit = struct.unpack("<H", f.read(2))[0]
  258. +       elif nit == 254:
  259. +               nit = struct.unpack("<I", f.read(4))[0]
  260. +       elif nit == 255:
  261. +               nit = struct.unpack("<Q", f.read(8))[0]
  262. +       r = []
  263. +       for i in xrange(nit):
  264. +               t = deser_uint256(f)
  265. +               r.append(t)
  266. +       return r
  267. +
  268. +def ser_uint256_vector(l):
  269. +       r = ""
  270. +       if len(l) < 253:
  271. +               r = chr(len(l))
  272. +       elif len(s) < 0x10000:
  273. +               r = chr(253) + struct.pack("<H", len(l))
  274. +       elif len(s) < 0x100000000L:
  275. +               r = chr(254) + struct.pack("<I", len(l))
  276. +       else:
  277. +               r = chr(255) + struct.pack("<Q", len(l))
  278. +       for i in l:
  279. +               r += ser_uint256(i)
  280. +       return r
  281. +
  282. +class CAddress(object):
  283. +       def __init__(self):
  284. +               self.nServices = 1
  285. +               self.pchReserved = "\x00" * 10 + "\xff" * 2
  286. +               self.ip = "0.0.0.0"
  287. +               self.port = 0
  288. +       def deserialize(self, f):
  289. +               self.nServices = struct.unpack("<Q", f.read(8))[0]
  290. +               self.pchReserved = f.read(12)
  291. +               self.ip = socket.inet_ntoa(f.read(4))
  292. +               self.port = struct.unpack(">H", f.read(2))[0]
  293. +       def serialize(self):
  294. +               r = ""
  295. +               r += struct.pack("<Q", self.nServices)
  296. +               r += self.pchReserved
  297. +               r += socket.inet_aton(self.ip)
  298. +               r += struct.pack(">H", self.port)
  299. +               return r
  300. +       def __repr__(self):
  301. +               return "CAddress(nServices=%i ip=%s port=%i)" % (self.nServices, self.ip, self.port)
  302. +
  303. +class CInv(object):
  304. +       typemap = {
  305. +               0: "Error",
  306. +               1: "TX",
  307. +               2: "Block"}
  308. +       def __init__(self):
  309. +               self.type = 0
  310. +               self.hash = 0L
  311. +       def deserialize(self, f):
  312. +               self.type = struct.unpack("<i", f.read(4))[0]
  313. +               self.hash = deser_uint256(f)
  314. +       def serialize(self):
  315. +               r = ""
  316. +               r += struct.pack("<i", self.type)
  317. +               r += ser_uint256(self.hash)
  318. +               return r
  319. +       def __repr__(self):
  320. +               return "CInv(type=%s hash=%064x)" % (self.typemap[self.type], self.hash)
  321. +
  322. +class CBlockLocator(object):
  323. +       def __init__(self):
  324. +               self.nVersion = MY_VERSION
  325. +               self.vHave = []
  326. +       def deserialize(self, f):
  327. +               self.nVersion = struct.unpack("<i", f.read(4))[0]
  328. +               self.vHave = deser_uint256_vector(f)
  329. +       def serialize(self):
  330. +               r = ""
  331. +               r += struct.pack("<i", self.nVersion)
  332. +               r += ser_uint256_vector(self.vHave)
  333. +               return r
  334. +       def __repr__(self):
  335. +               return "CBlockLocator(nVersion=%i vHave=%s)" % (self.nVersion, repr(self.vHave))
  336. +
  337. +class COutPoint(object):
  338. +       def __init__(self):
  339. +               self.hash = 0
  340. +               self.n = 0
  341. +       def deserialize(self, f):
  342. +               self.hash = deser_uint256(f)
  343. +               self.n = struct.unpack("<I", f.read(4))[0]
  344. +       def serialize(self):
  345. +               r = ""
  346. +               r += ser_uint256(self.hash)
  347. +               r += struct.pack("<I", self.n)
  348. +               return r
  349. +       def __repr__(self):
  350. +               return "COutPoint(hash=%064x n=%i)" % (self.hash, self.n)
  351. +
  352. +class CTxIn(object):
  353. +       def __init__(self):
  354. +               self.prevout = COutPoint()
  355. +               self.scriptSig = ""
  356. +               self.nSequence = 0
  357. +       def deserialize(self, f):
  358. +               self.prevout = COutPoint()
  359. +               self.prevout.deserialize(f)
  360. +               self.scriptSig = deser_string(f)
  361. +               self.nSequence = struct.unpack("<I", f.read(4))[0]
  362. +       def serialize(self):
  363. +               r = ""
  364. +               r += self.prevout.serialize()
  365. +               r += ser_string(self.scriptSig)
  366. +               r += struct.pack("<I", self.nSequence)
  367. +               return r
  368. +       def __repr__(self):
  369. +               return "CTxIn(prevout=%s scriptSig=%s nSequence=%i)" % (repr(self.prevout), binascii.hexlify(self.scriptSig), self.nSequence)
  370. +
  371. +class CTxOut(object):
  372. +       def __init__(self):
  373. +               self.nValue = 0
  374. +               self.scriptPubKey = ""
  375. +       def deserialize(self, f):
  376. +               self.nValue = struct.unpack("<q", f.read(8))[0]
  377. +               self.scriptPubKey = deser_string(f)
  378. +       def serialize(self):
  379. +               r = ""
  380. +               r += struct.pack("<q", self.nValue)
  381. +               r += ser_string(self.scriptPubKey)
  382. +               return r
  383. +       def __repr__(self):
  384. +               return "CTxOut(nValue=%i.%08i scriptPubKey=%s)" % (self.nValue // 100000000, self.nValue % 100000000, binascii.hexlify(self.scriptPubKey))
  385. +
  386. +class CTransaction(object):
  387. +       def __init__(self):
  388. +               self.nVersion = 1
  389. +               self.vin = []
  390. +               self.vout = []
  391. +               self.nLockTime = 0
  392. +               self.sha256 = None
  393. +       def deserialize(self, f):
  394. +               self.nVersion = struct.unpack("<i", f.read(4))[0]
  395. +               self.vin = deser_vector(f, CTxIn)
  396. +               self.vout = deser_vector(f, CTxOut)
  397. +               self.nLockTime = struct.unpack("<I", f.read(4))[0]
  398. +       def serialize(self):
  399. +               r = ""
  400. +               r += struct.pack("<i", self.nVersion)
  401. +               r += ser_vector(self.vin)
  402. +               r += ser_vector(self.vout)
  403. +               r += struct.pack("<I", self.nLockTime)
  404. +               return r
  405. +       def calc_sha256(self):
  406. +               if self.sha256 is None:
  407. +                       self.sha256 = uint256_from_str(SHA256.new(SHA256.new(self.serialize()).digest()).digest())
  408. +       def is_valid(self):
  409. +               self.calc_sha256()
  410. +               for tout in self.vout:
  411. +                       if tout.nValue < 0 or tout.nValue > 21000000L * 100000000L:
  412. +                               return False
  413. +               return True
  414. +       def __repr__(self):
  415. +               return "CTransaction(nVersion=%i vin=%s vout=%s nLockTime=%i)" % (self.nVersion, repr(self.vin), repr(self.vout), self.nLockTime)
  416. +
  417. +class CBlock(object):
  418. +       def __init__(self):
  419. +               self.nVersion = 1
  420. +               self.hashPrevBlock = 0
  421. +               self.hashMerkleRoot = 0
  422. +               self.nTime = 0
  423. +               self.nBits = 0
  424. +               self.nNonce = 0
  425. +               self.vtx = []
  426. +               self.sha256 = None
  427. +       def deserialize(self, f):
  428. +               self.nVersion = struct.unpack("<i", f.read(4))[0]
  429. +               self.hashPrevBlock = deser_uint256(f)
  430. +               self.hashMerkleRoot = deser_uint256(f)
  431. +               self.nTime = struct.unpack("<I", f.read(4))[0]
  432. +               self.nBits = struct.unpack("<I", f.read(4))[0]
  433. +               self.nNonce = struct.unpack("<I", f.read(4))[0]
  434. +               self.vtx = deser_vector(f, CTransaction)
  435. +       def serialize(self):
  436. +               r = ""
  437. +               r += struct.pack("<i", self.nVersion)
  438. +               r += ser_uint256(self.hashPrevBlock)
  439. +               r += ser_uint256(self.hashMerkleRoot)
  440. +               r += struct.pack("<I", self.nTime)
  441. +               r += struct.pack("<I", self.nBits)
  442. +               r += struct.pack("<I", self.nNonce)
  443. +               r += ser_vector(self.vtx)
  444. +               return r
  445. +       def calc_sha256(self):
  446. +               if self.sha256 is None:
  447. +                       r = ""
  448. +                       r += struct.pack("<i", self.nVersion)
  449. +                       r += ser_uint256(self.hashPrevBlock)
  450. +                       r += ser_uint256(self.hashMerkleRoot)
  451. +                       r += struct.pack("<I", self.nTime)
  452. +                       r += struct.pack("<I", self.nBits)
  453. +                       r += struct.pack("<I", self.nNonce)
  454. +                       self.sha256 = uint256_from_str(SHA256.new(SHA256.new(r).digest()).digest())
  455. +       def is_valid(self):
  456. +               self.calc_sha256()
  457. +               target = uint256_from_compact(self.nBits)
  458. +               if self.sha256 > target:
  459. +                       return False
  460. +               hashes = []
  461. +               for tx in self.vtx:
  462. +                       if not tx.is_valid():
  463. +                               return False
  464. +                       tx.calc_sha256()
  465. +                       hashes.append(ser_uint256(tx.sha256))
  466. +               while len(hashes) > 1:
  467. +                       newhashes = []
  468. +                       for i in xrange(0, len(hashes), 2):
  469. +                               i2 = min(i+1, len(hashes)-1)
  470. +                               newhashes.append(SHA256.new(SHA256.new(hashes[i] + hashes[i2]).digest()).digest())
  471. +                       hashes = newhashes
  472. +               if uint256_from_str(hashes[0]) != self.hashMerkleRoot:
  473. +                       return False
  474. +               return True
  475. +       def __repr__(self):
  476. +               return "CBlock(nVersion=%i hashPrevBlock=%064x hashMerkleRoot=%064x nTime=%s nBits=%08x nNonce=%08x vtx=%s)" % (self.nVersion, self.hashPrevBlock, self.hashMerkleRoot, time.ctime(self.nTime), self.nBits, self.nNonce, repr(self.vtx))
  477. +
  478. +class msg_version(object):
  479. +       command = "version"
  480. +       def __init__(self):
  481. +               self.nVersion = MY_VERSION
  482. +               self.nServices = 1
  483. +               self.nTime = time.time()
  484. +               self.addrTo = CAddress()
  485. +               self.addrFrom = CAddress()
  486. +               self.nNonce = random.getrandbits(64)
  487. +               self.strSubVer = MY_SUBVERSION
  488. +               self.nStartingHeight = -1
  489. +       def deserialize(self, f):
  490. +               self.nVersion = struct.unpack("<i", f.read(4))[0]
  491. +               if self.nVersion == 10300:
  492. +                       self.nVersion = 300
  493. +               self.nServices = struct.unpack("<Q", f.read(8))[0]
  494. +               self.nTime = struct.unpack("<q", f.read(8))[0]
  495. +               self.addrTo = CAddress()
  496. +               self.addrTo.deserialize(f)
  497. +               if self.nVersion >= 106:
  498. +                       self.addrFrom = CAddress()
  499. +                       self.addrFrom.deserialize(f)
  500. +                       self.nNonce = struct.unpack("<Q", f.read(8))[0]
  501. +                       self.strSubVer = deser_string(f)
  502. +                       if self.nVersion >= 209:
  503. +                               self.nStartingHeight = struct.unpack("<i", f.read(4))[0]
  504. +                       else:
  505. +                               self.nStartingHeight = None
  506. +               else:
  507. +                       self.addrFrom = None
  508. +                       self.nNonce = None
  509. +                       self.strSubVer = None
  510. +                       self.nStartingHeight = None
  511. +       def serialize(self):
  512. +               r = ""
  513. +               r += struct.pack("<i", self.nVersion)
  514. +               r += struct.pack("<Q", self.nServices)
  515. +               r += struct.pack("<q", self.nTime)
  516. +               r += self.addrTo.serialize()
  517. +               r += self.addrFrom.serialize()
  518. +               r += struct.pack("<Q", self.nNonce)
  519. +               r += ser_string(self.strSubVer)
  520. +               r += struct.pack("<i", self.nStartingHeight)
  521. +               return r
  522. +       def __repr__(self):
  523. +               return "msg_version(nVersion=%i nServices=%i nTime=%s addrTo=%s addrFrom=%s nNonce=0x%016X strSubVer=%s nStartingHeight=%i)" % (self.nVersion, self.nServices, time.ctime(self.nTime), repr(self.addrTo), repr(self.addrFrom), self.nNonce, self.strSubVer, self.nStartingHeight)
  524. +
  525. +class msg_verack(object):
  526. +       command = "verack"
  527. +       def __init__(self):
  528. +               pass
  529. +       def deserialize(self, f):
  530. +               pass
  531. +       def serialize(self):
  532. +               return ""
  533. +       def __repr__(self):
  534. +               return "msg_verack()"
  535. +
  536. +class msg_addr(object):
  537. +       command = "addr"
  538. +       def __init__(self):
  539. +               self.addrs = []
  540. +       def deserialize(self, f):
  541. +               self.addrs = deser_vector(f, CAddress)
  542. +       def serialize(self):
  543. +               return ser_vector(self.addrs)
  544. +       def __repr__(self):
  545. +               return "msg_addr(addrs=%s)" % (repr(self.addrs))
  546. +
  547. +class msg_inv(object):
  548. +       command = "inv"
  549. +       def __init__(self):
  550. +               self.inv = []
  551. +       def deserialize(self, f):
  552. +               self.inv = deser_vector(f, CInv)
  553. +       def serialize(self):
  554. +               return ser_vector(self.inv)
  555. +       def __repr__(self):
  556. +               return "msg_inv(inv=%s)" % (repr(self.inv))
  557. +
  558. +class msg_getdata(object):
  559. +       command = "getdata"
  560. +       def __init__(self):
  561. +               self.inv = []
  562. +       def deserialize(self, f):
  563. +               self.inv = deser_vector(f, CInv)
  564. +       def serialize(self):
  565. +               return ser_vector(self.inv)
  566. +       def __repr__(self):
  567. +               return "msg_getdata(inv=%s)" % (repr(self.inv))
  568. +
  569. +class msg_getblocks(object):
  570. +       command = "getblocks"
  571. +       def __init__(self):
  572. +               self.locator = CBlockLocator()
  573. +               self.hashstop = 0L
  574. +       def deserialize(self, f):
  575. +               self.locator = CBlockLocator()
  576. +               self.locator.deserialize(f)
  577. +               self.hashstop = deser_uint256(f)
  578. +       def serialize(self):
  579. +               r = ""
  580. +               r += self.locator.serialize()
  581. +               r += ser_uint256(self.hashstop)
  582. +               return r
  583. +       def __repr__(self):
  584. +               return "msg_getblocks(locator=%s hashstop=%064x)" % (repr(self.locator), self.hashstop)
  585. +
  586. +class msg_tx(object):
  587. +       command = "tx"
  588. +       def __init__(self):
  589. +               self.tx = CTransaction()
  590. +       def deserialize(self, f):
  591. +               self.tx.deserialize(f)
  592. +       def serialize(self):
  593. +               return self.tx.serialize()
  594. +       def __repr__(self):
  595. +               return "msg_tx(tx=%s)" % (repr(self.tx))
  596. +
  597. +class msg_block(object):
  598. +       command = "block"
  599. +       def __init__(self):
  600. +               self.block = CBlock()
  601. +       def deserialize(self, f):
  602. +               self.block.deserialize(f)
  603. +       def serialize(self):
  604. +               return self.block.serialize()
  605. +       def __repr__(self):
  606. +               return "msg_block(block=%s)" % (repr(self.block))
  607. +
  608. +class msg_getaddr(object):
  609. +       command = "getaddr"
  610. +       def __init__(self):
  611. +               pass
  612. +       def deserialize(self, f):
  613. +               pass
  614. +       def serialize(self):
  615. +               return ""
  616. +       def __repr__(self):
  617. +               return "msg_getaddr()"
  618. +
  619. +#msg_checkorder
  620. +#msg_submitorder
  621. +#msg_reply
  622. +
  623. +class msg_ping(object):
  624. +       command = "ping"
  625. +       def __init__(self):
  626. +               pass
  627. +       def deserialize(self, f):
  628. +               pass
  629. +       def serialize(self):
  630. +               return ""
  631. +       def __repr__(self):
  632. +               return "msg_ping()"
  633. +
  634. +
  635. +
  636. +
  637. +
  638. +
  639. +class BitcoinNode(threading.Thread):
  640. +       messagemap = {
  641. +               "version": msg_version,
  642. +               "verack": msg_verack,
  643. +               "addr": msg_addr,
  644. +               "inv": msg_inv,
  645. +               "getdata": msg_getdata,
  646. +               "getblocks": msg_getblocks,
  647. +               "tx": msg_tx,
  648. +               "block": msg_block,
  649. +               "getaddr": msg_getaddr,
  650. +               "ping": msg_ping
  651. +       }
  652. +       def __init__(self, dstaddr, dstport):
  653. +               threading.Thread.__init__(self)
  654. +               self.dstaddr = dstaddr
  655. +               self.dstport = dstport
  656. +               self.sendbuf = ""
  657. +               self.recvbuf = ""
  658. +               self.ver_send = 0
  659. +               self.ver_recv = 0
  660. +               self.last_sent = 0
  661. +               self.state = "idle"
  662. +               self.e_stop = threading.Event()
  663. +
  664. +       def stop(self):
  665. +               self.e_stop.set()
  666. +
  667. +       def run(self):
  668. +               self.state = "connecting"
  669. +               print "connecting %s" % self.dstaddr
  670. +               self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  671. +               try:
  672. +                       self.socket.settimeout(120)
  673. +                       self.socket.connect((self.dstaddr, self.dstport))
  674. +               except:
  675. +                       self.handle_close()
  676. +
  677. +               self.handle_connect()
  678. +
  679. +               epoll = select.epoll()
  680. +               epoll.register(self.socket.fileno(), select.EPOLLIN)
  681. +
  682. +               while self.state != "closed":
  683. +                       if self.e_stop.isSet():
  684. +                               break
  685. +
  686. +                       events = epoll.poll(timeout=1)
  687. +                       for fd, ev in events:
  688. +                               if ev & select.EPOLLIN:
  689. +                                       self.handle_read()
  690. +                               elif ev & select.EPOLLHUP:
  691. +                                       self.handle_close()
  692. +
  693. +                       self.handle_write()
  694. +
  695. +               self.handle_close()
  696. +
  697. +       def handle_connect(self):
  698. +               self.state = "connected"
  699. +               print "connected"
  700. +               #send version msg
  701. +               t = msg_version()
  702. +               t.addrTo.ip = self.dstaddr
  703. +               t.addrTo.port = self.dstport
  704. +               t.addrFrom.ip = "0.0.0.0"
  705. +               t.addrFrom.port = 0
  706. +               self.send_message(t)
  707. +
  708. +       def handle_close(self):
  709. +               print "close"
  710. +               self.state = "closed"
  711. +               self.recvbuf = ""
  712. +               self.sendbuf = ""
  713. +               try:
  714. +                       self.close()
  715. +               except:
  716. +                       pass
  717. +       def handle_read(self):
  718. +               try:
  719. +                       t = self.socket.recv(8192)
  720. +               except:
  721. +                       self.handle_close()
  722. +                       return
  723. +               if len(t) == 0:
  724. +                       self.handle_close()
  725. +                       return
  726. +               self.recvbuf += t
  727. +               self.got_data()
  728. +       def readable(self):
  729. +               return True
  730. +       def writable(self):
  731. +               return (len(self.sendbuf) > 0)
  732. +       def handle_write(self):
  733. +               try:
  734. +                       sent = self.socket.send(self.sendbuf)
  735. +               except:
  736. +                       self.handle_close()
  737. +                       return
  738. +               self.sendbuf = self.sendbuf[sent:]
  739. +       def got_data(self):
  740. +               while True:
  741. +                       if len(self.recvbuf) < 4:
  742. +                               return
  743. +                       if self.recvbuf[:4] != "\xf9\xbe\xb4\xd9":
  744. +                               raise ValueError("got garbage %s" % repr(self.recvbuf))
  745. +                       if self.ver_recv < 209:
  746. +                               if len(self.recvbuf) < 4 + 12 + 4:
  747. +                                       return
  748. +                               command = self.recvbuf[4:4+12].split("\x00", 1)[0]
  749. +                               msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0]
  750. +                               checksum = None
  751. +                               if len(self.recvbuf) < 4 + 12 + 4 + msglen:
  752. +                                       return
  753. +                               msg = self.recvbuf[4+12+4:4+12+4+msglen]
  754. +                               self.recvbuf = self.recvbuf[4+12+4+msglen:]
  755. +                       else:
  756. +                               if len(self.recvbuf) < 4 + 12 + 4 + 4:
  757. +                                       return
  758. +                               command = self.recvbuf[4:4+12].split("\x00", 1)[0]
  759. +                               msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0]
  760. +                               checksum = self.recvbuf[4+12+4:4+12+4+4]
  761. +                               if len(self.recvbuf) < 4 + 12 + 4 + 4 + msglen:
  762. +                                       return
  763. +                               msg = self.recvbuf[4+12+4+4:4+12+4+4+msglen]
  764. +                               th = SHA256.new(msg).digest()
  765. +                               h = SHA256.new(th).digest()
  766. +                               if checksum != h[:4]:
  767. +                                       raise ValueError("got bad checksum %s" % repr(self.recvbuf))
  768. +                               self.recvbuf = self.recvbuf[4+12+4+4+msglen:]
  769. +                       if command in self.messagemap:
  770. +                               f = cStringIO.StringIO(msg)
  771. +                               t = self.messagemap[command]()
  772. +                               t.deserialize(f)
  773. +                               self.got_message(t)
  774. +                       else:
  775. +                               print "UNKNOWN COMMAND", command, repr(msg)
  776. +       def send_message(self, message):
  777. +               if self.state != "connected":
  778. +                       return
  779. +               #print "send %s" % repr(message)
  780. +               command = message.command
  781. +               data = message.serialize()
  782. +               tmsg = "\xf9\xbe\xb4\xd9"
  783. +               tmsg += command
  784. +               tmsg += "\x00" * (12 - len(command))
  785. +               tmsg += struct.pack("<I", len(data))
  786. +               if self.ver_send >= 209:
  787. +                       th = SHA256.new(data).digest()
  788. +                       h = SHA256.new(th).digest()
  789. +                       tmsg += h[:4]
  790. +               tmsg += data
  791. +               self.sendbuf += tmsg
  792. +               self.last_sent = time.time()
  793. +       def got_message(self, message):
  794. +               if self.last_sent + 30 * 60 < time.time():
  795. +                       self.send_message(msg_ping())
  796. +
  797. +               mname = 'do_' + message.command
  798. +               if not hasattr(self, mname):
  799. +                       return
  800. +
  801. +               method = getattr(self, mname)
  802. +               method(message)
  803. +
  804. +
  805. +#              if message.command == "tx":
  806. +#                      message.tx.calc_sha256()
  807. +#                      sha256 = message.tx.sha256
  808. +#                      pubkey = binascii.hexlify(message.tx.vout[0].scriptPubKey)
  809. +#                      txlock.acquire()
  810. +#                      tx.append([str(sha256), str(time.time()), str(self.dstaddr), pubkey])
  811. +#                      txlock.release()
  812. +
  813. +       def do_version(self, message):
  814. +               if message.nVersion >= 209:
  815. +                       self.send_message(msg_verack())
  816. +               self.ver_send = min(MY_VERSION, message.nVersion)
  817. +               if message.nVersion < 209:
  818. +                       self.ver_recv = self.ver_send
  819. +
  820. +       def do_verack(self, message):
  821. +                       self.ver_recv = self.ver_send
  822. +
  823. +       def do_inv(self, message):
  824. +               want = msg_getdata()
  825. +               for i in message.inv:
  826. +                       if i.type == 1:
  827. +                               want.inv.append(i)
  828. +                       elif i.type == 2:
  829. +                               want.inv.append(i)
  830. +               if len(want.inv):
  831. +                       self.send_message(want)
  832. +
  833. diff --git a/poclbm.py b/poclbm.py
  834. index 267d6ef..6077a7a 100644
  835. --- a/poclbm.py
  836. +++ b/poclbm.py
  837. @@ -27,5 +27,5 @@ if (options.device == -1 or options.device >= len(devices)):
  838.         sys.exit()
  839.  
  840.  context = cl.Context([devices[options.device]], None, None)
  841. -myMiner = BitcoinMiner(platform, context, options.host, options.user, options.password, options.port, options.frames, options.rate, options.askrate, options.worksize, options.vectors)
  842. -myMiner.mine()
  843. \ No newline at end of file
  844. +myMiner = BitcoinMiner(platform, context, options.device, options.host, options.user, options.password, options.port, options.frames, options.rate, options.askrate, options.worksize, options.vectors)
  845. +myMiner.mine()