This repository has been archived by the owner on May 23, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 23
/
block_template.py
159 lines (128 loc) · 6.05 KB
/
block_template.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import StringIO
import binascii
import struct
import util
import merkletree
import halfnode
from coinbasetx import CoinbaseTransactionPOW
from coinbasetx import CoinbaseTransactionPOS
from coinbasetx import CoinbaseTransaction
import lib.logger
log = lib.logger.get_logger('block_template')
import lib.logger
log = lib.logger.get_logger('block_template')
# Remove dependency to settings, coinbase extras should be
# provided from coinbaser
import settings
class BlockTemplate(halfnode.CBlock):
'''Template is used for generating new jobs for clients.
Let's iterate extranonce1, extranonce2, ntime and nonce
to find out valid coin block!'''
coinbase_transaction_class = CoinbaseTransaction
def __init__(self, timestamper, coinbaser, job_id):
log.debug("Got To Block_template.py")
log.debug("Got To Block_template.py")
super(BlockTemplate, self).__init__()
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.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 = []
def fill_from_rpc(self, data):
'''Convert getblocktemplate result into BlockTemplate instance'''
payee = None
if(data['payee'] != ''): payee = util.script_to_address(data['payee'])
#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 = CoinbaseTransactionPOW(self.timestamper, self.coinbaser, payee, 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.nBits = int(data['bits'], 16)
self.hashMerkleRoot = 0
self.nTime = 0
self.nNonce = 0
self.masternode_payments = data['masternode_payments']
self.vtx = [ coinbase, ]
for vote in data['votes']:
v = halfnode.CMasterNodeVote()
v.deserialize(StringIO.StringIO(binascii.unhexlify(vote)))
self.vmn.append(v)
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.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
their unique extranonce1 into the coinbase, so every
coinbase_hash (and then merkle_root) will be unique as well.'''
job_id = self.job_id
prevhash = binascii.hexlify(self.prevhash_bin)
(coinb1, coinb2) = [ binascii.hexlify(x) for x in self.vtx[0]._serialized ]
merkle_branch = [ binascii.hexlify(x) for x in self.merkletree._steps ]
version = binascii.hexlify(struct.pack(">i", self.nVersion))
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):
'''Serialize coinbase with given extranonce1 and 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() + 7200):
# 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):
'''Serialize header for calculating block hash'''
r = struct.pack(">i", self.nVersion)
r += self.prevhash_bin
r += util.ser_uint256_be(merkle_root_int)
r += ntime_bin
r += struct.pack(">I", self.nBits)
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.sha256 = None # We changed block parameters, let's reset sha256 cache