'''Template is used for generating new jobs for clients.
Let's iterate extranonce1, extranonce2, ntime and nonce
to find out valid bitcoin block!'''
-
+
coinbase_transaction_class = CoinbaseTransaction
-
+
def __init__(self, timestamper, coinbaser, job_id):
super(BlockTemplate, self).__init__()
-
- self.job_id = job_id
+
+ self.job_id = job_id
self.timestamper = timestamper
self.coinbaser = coinbaser
-
+
self.prevhash_bin = '' # reversed binary form of prevhash
self.prevhash_hex = ''
self.timedelta = 0
self.curtime = 0
self.target = 0
- #self.coinbase_hex = None
+ #self.coinbase_hex = None
self.merkletree = None
-
+
self.broadcast_args = []
-
+
# List of 4-tuples (extranonce1, extranonce2, ntime, nonce)
# registers already submitted and checked shares
# There may be registered also invalid shares inside!
- self.submits = []
-
+ self.submits = []
+
def fill_from_rpc(self, data):
'''Convert getblocktemplate result into BlockTemplate instance'''
-
+
#txhashes = [None] + [ binascii.unhexlify(t['hash']) for t in data['transactions'] ]
txhashes = [None] + [ util.ser_uint256(int(t['hash'], 16)) for t in data['transactions'] ]
mt = merkletree.MerkleTree(txhashes)
coinbase = self.coinbase_transaction_class(self.timestamper, self.coinbaser, data['coinbasevalue'],
data['coinbaseaux']['flags'], data['height'], settings.COINBASE_EXTRAS)
-
+
self.height = data['height']
self.nVersion = data['version']
self.hashPrevBlock = int(data['previousblockhash'], 16)
self.nTime = 0
self.nNonce = 0
self.vtx = [ coinbase, ]
-
+
for tx in data['transactions']:
t = halfnode.CTransaction()
t.deserialize(StringIO.StringIO(binascii.unhexlify(tx['data'])))
self.vtx.append(t)
-
+
self.curtime = data['curtime']
- self.timedelta = self.curtime - int(self.timestamper.time())
+ self.timedelta = self.curtime - int(self.timestamper.time())
self.merkletree = mt
self.target = util.uint256_from_compact(self.nBits)
-
+
# Reversed prevhash
self.prevhash_bin = binascii.unhexlify(util.reverse_hash(data['previousblockhash']))
self.prevhash_hex = "%064x" % self.hashPrevBlock
-
+
self.broadcast_args = self.build_broadcast_args()
-
+
def register_submit(self, extranonce1, extranonce2, ntime, nonce):
'''Client submitted some solution. Let's register it to
prevent double submissions.'''
-
+
t = (extranonce1, extranonce2, ntime, nonce)
if t not in self.submits:
self.submits.append(t)
return True
return False
-
+
def build_broadcast_args(self):
'''Build parameters of mining.notify call. All clients
may receive the same params, because they include
nbits = binascii.hexlify(struct.pack(">I", self.nBits))
ntime = binascii.hexlify(struct.pack(">I", self.curtime))
clean_jobs = True
-
+
return (job_id, prevhash, coinb1, coinb2, merkle_branch, version, nbits, ntime, clean_jobs)
def serialize_coinbase(self, extranonce1, extranonce2):
in binary form'''
(part1, part2) = self.vtx[0]._serialized
return part1 + extranonce1 + extranonce2 + part2
-
+
def check_ntime(self, ntime):
'''Check for ntime restrictions.'''
if ntime < self.curtime:
return False
-
+
if ntime > (self.timestamper.time() + 1000):
# Be strict on ntime into the near future
# may be unnecessary
return False
-
+
return True
def serialize_header(self, merkle_root_int, ntime_bin, nonce_bin):
r += util.ser_uint256_be(merkle_root_int)
r += ntime_bin
r += struct.pack(">I", self.nBits)
- r += nonce_bin
- return r
+ r += nonce_bin
+ return r
def finalize(self, merkle_root_int, extranonce1_bin, extranonce2_bin, ntime, nonce):
'''Take all parameters required to compile block candidate.
self.is_valid() should return True then...'''
-
+
self.hashMerkleRoot = merkle_root_int
self.nTime = ntime
self.nNonce = nonce
- self.vtx[0].set_extranonce(extranonce1_bin + extranonce2_bin)
+ self.vtx[0].set_extranonce(extranonce1_bin + extranonce2_bin)
self.sha256 = None # We changed block parameters, let's reset sha256 cache