コード例 #1
0
    def fill_from_rpc(self, data):
        '''Convert getblocktemplate result into BlockTemplate instance'''

        commitment = None
        nTime = data['curtime'] if data.has_key('curtime') else None

        if settings.COINDAEMON_HAS_SEGWIT:
            txids = []
            hashes = [None] + [ util.ser_uint256(int(t['hash'], 16)) for t in data['transactions'] ]
            try:
                txids = [None] + [ util.ser_uint256(int(t['txid'], 16)) for t in data['transactions'] ]
                mt = merkletree.MerkleTree(txids)
            except KeyError:
                mt = merkletree.MerkleTree(hashes)

            wmt = merkletree.MerkleTree(hashes).withFirst(binascii.unhexlify('0000000000000000000000000000000000000000000000000000000000000000'))
            self.witness = SHA256.new(SHA256.new(wmt + witness_nonce).digest()).digest()
            commitment = b'\x6a' + struct.pack(">b", len(self.witness) + len(witness_magic)) + witness_magic + self.witness
            try:
                default_witness = data['default_witness_commitment']
                commitment_check = binascii.unhexlify(default_witness)
                if(commitment != commitment_check):
                    print("calculated witness does not match supplied one! This block probably will not be accepted!")
                    commitment = commitment_check
            except KeyError:
                 pass
            self.witness = commitment[6:]
        else:
            txhashes = [None] + [ util.ser_uint256(int(t['hash'], 16)) for t in data['transactions'] ]
            mt = merkletree.MerkleTree(txhashes)

        coinbase = CoinbaseTransaction(self.timestamper, self.coinbaser, data['coinbasevalue'],
                                              data['coinbaseaux']['flags'], data['height'],
                                              commitment, settings.COINBASE_EXTRAS, nTime)

        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.vtx = [ coinbase, ]

        for tx in data['transactions']:
            t = TxBlob()
            t.deserialize(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()
コード例 #2
0
 def serialize_header(self, merkle_root_int, ntime_bin, nonce_bin):
     '''Serialize header for calculating block hash'''
     r  = struct.pack("<i", self.nVersion)
     r += util.ser_uint256(self.hashPrevBlock)
     r += util.ser_uint256(merkle_root_int)
     r += ntime_bin[::-1]
     r += struct.pack("<I", self.nBits)
     r += nonce_bin[::-1]    
     return r   
コード例 #3
0
 def serialize_header(self, merkle_root_int, ntime_bin, nonce_bin):
     '''Serialize header for calculating block hash'''
     r = struct.pack("<i", self.nVersion)
     r += util.ser_uint256(self.hashPrevBlock)
     r += util.ser_uint256(merkle_root_int)
     r += ntime_bin[::-1]
     r += struct.pack("<I", self.nBits)
     r += nonce_bin[::-1]
     return r
コード例 #4
0
 def serialize(self):
     r = []
     r.append(struct.pack("<i", self.nVersion))
     r.append(util.ser_uint256(self.hashPrevBlock))
     r.append(util.ser_uint256(self.hashMerkleRoot))
     r.append(struct.pack("<I", self.nTime))
     r.append(struct.pack("<I", self.nBits))
     r.append(struct.pack("<I", self.nNonce))
     r.append(util.ser_vector(self.vtx))
     return ''.join(r)
コード例 #5
0
 def serialize(self):
     r = []
     r.append(struct.pack("<i", self.nVersion))
     r.append(util.ser_uint256(self.hashPrevBlock))
     r.append(util.ser_uint256(self.hashMerkleRoot))
     r.append(struct.pack("<I", self.nTime))
     r.append(struct.pack("<I", self.nBits))
     r.append(struct.pack("<I", self.nNonce))
     r.append(util.ser_vector(self.vtx))
     return ''.join(r)
コード例 #6
0
 def serialize(self):
     r = [
         struct.pack("<i", self.nVersion),
         util.ser_uint256(self.hashPrevBlock),
         util.ser_uint256(self.hashMerkleRoot),
         struct.pack("<I", self.nTime),
         struct.pack("<I", self.nBits),
         struct.pack("<I", self.nNonce),
         util.ser_vector(self.vtx)
     ]
     return ''.join(r)
コード例 #7
0
    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.nBits = int(data['bits'], 16)
        self.hashMerkleRoot = 0
        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.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()
コード例 #8
0
    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.nBits = int(data['bits'], 16)
        self.hashMerkleRoot = 0
        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.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()
コード例 #9
0
 def serialize(self):
     r = []
     r.append(struct.pack("<i", self.nVersion))
     r.append(util.ser_uint256(self.hashPrevBlock))
     r.append(util.ser_uint256(self.hashMerkleRoot))
     r.append(struct.pack("<I", self.nTime))
     r.append(struct.pack("<I", self.nBits))
     r.append(struct.pack("<I", self.nNonce))
     r.append(util.ser_uint256(self.hashstateroot))
     r.append(util.ser_uint256(self.hashutxoroot))
     r.append(
         binascii.unhexlify(
             "0000000000000000000000000000000000000000000000000000000000000000ffffffff00"
         ))
     r.append(util.ser_vector(self.vtx))
     return ''.join(r)
コード例 #10
0
    def fill_from_rpc(self, data):
        '''Convert getblocktemplate result into BlockTemplate instance'''

        payee = None
        if (data['payee'] != ''): payee = util.script_to_address(data['payee'])

        payee_amount = data.get('payee_amount',
                                data['coinbasevalue'] / 5)  #default to 20%

        #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, payee_amount,
                                          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()
コード例 #11
0
 def __init__(self, root):
     if type(root) == long:
         root = util.ser_uint256(root)
     self.valid = [root, [], []]
     self.state = TreeState()
     # A dict for purgatory is a bit of a hack, and should probably be fixed before switching to C++.
     self.purgatory = {} # key = (level, index); value = [candidate hashes]
     self.peerorigins = {} # key = hash, value = peer
     self.txcounthints = [] # we can't trust it when a peer says how many txes there are, so they're just hints
     self.levels = 0
     self.txcount = 0
コード例 #12
0
    def fill_from_rpc(self, data, aux_data):
        '''Convert getblocktemplate result into BlockTemplate instance'''

        self.auxs = aux_data
        self.tree, self.merkle_size = util.make_auxpow_tree(aux_data)
        self.aux_targets = [None for i in self.auxs]
        merkle_leaves = [ ('0' * 64) for x in range(self.merkle_size) ]

        for chain in range(len(self.auxs)):
            merkle_index = self.tree[self.auxs[chain]['chainid']]
            merkle_leaves[merkle_index] = self.auxs[chain]['hash']
            target = self.auxs[chain]['target'].decode('hex')[::-1].encode('hex')
            self.aux_targets[chain] = int(target, 16)
            log.info("Merged Chain: %i network difficulty: %s" % (self.auxs[chain]['chainid'], float(util.diff_to_target(self.aux_targets[chain]))))

        self.merkle_hashes = [ int(t, 16) for t in merkle_leaves ]
        self.mm_data = '\xfa\xbemm' + util.aux_pow_coinbase_type.pack(dict(
            merkle_root = util.merkle_hash(self.merkle_hashes),
            size = self.merkle_size,
            nonce = 0,
        ))

        txhashes = [None] + [ util.ser_uint256(int(t['hash'], 16)) for t in data['transactions'] ]
        mt = merkletree.MerkleTree(txhashes)

        coinbase = CoinbaseTransaction(self.timestamper, self.coinbaser, data['coinbasevalue'],
                                              data['coinbaseaux']['flags'], data['height'],
                                              settings.COINBASE_EXTRAS + self.mm_data, data['curtime'])
            
        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.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.merkletree = mt
        self.target = util.uint256_from_compact(self.nBits)
        log.info("MainNet Block Height: %i network difficulty: %s" % (self.height, float(util.diff_to_target(self.target))))

        # 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()
コード例 #13
0
 def __init__(self, root):
     if type(root) == long:
         root = util.ser_uint256(root)
     self.valid = [root, [], []]
     self.state = TreeState()
     # A dict for purgatory is a bit of a hack, and should probably be fixed before switching to C++.
     self.purgatory = {}  # key = (level, index); value = [candidate hashes]
     self.peerorigins = {}  # key = hash, value = peer
     self.levels = 0
     self.txcount = 0
     self.runs = 0  # number of runs added; used to help decide when to send a new state to peers
     self.rwlock = rwlock.ReadWriteLock()
コード例 #14
0
 def __init__(self, root):
     if type(root) == long:
         root = util.ser_uint256(root)
     self.valid = [root, [], []]
     self.state = TreeState()
     # A dict for purgatory is a bit of a hack, and should probably be fixed before switching to C++.
     self.purgatory = {}  # key = (level, index); value = [candidate hashes]
     self.peerorigins = {}  # key = hash, value = peer
     self.txcounthints = [
     ]  # we can't trust it when a peer says how many txes there are, so they're just hints
     self.levels = 0
     self.txcount = 0
コード例 #15
0
    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)

        if settings.MAIN_COIN_TYPE == "proof-of-work":
            coinbase = self.coinbase_transaction_class(
                self.timestamper,
                self.coinbaser,
                data["coinbasevalue"],
                data["coinbaseaux"]["flags"],
                data["height"],
                settings.COINBASE_EXTRAS,
            )
        else:
            coinbase = self.coinbase_transaction_class(
                self.timestamper,
                self.coinbaser,
                data["coinbasevalue"],
                data["coinbaseaux"]["flags"],
                data["height"],
                settings.COINBASE_EXTRAS,
                data["curtime"],
            )

        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.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.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()
コード例 #16
0
    def fill_from_rpc(self, data):
        '''Convert getblocktemplate result into BlockTemplate instance'''
        
        payee = None
        if(data['payee'] != ''): payee = util.script_to_address(data['payee'])

        payee_amount = data.get('payee_amount', data['coinbasevalue']/5) #default to 20%

        #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, payee_amount, 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()
コード例 #17
0
 def calcparent(self, hash1, hash2):
     if type(hash1) == long:
         hash1 = util.ser_uint256(hash1)
     if type(hash2) == long:
         hash2 = util.ser_uint256(hash2)
     return util.doublesha(hash1 + hash2)
コード例 #18
0
    def addhash(self, level, index, hash, peer=None, locked=False):
        """
        Adds a hash to either the validated tree (when possible) or to the
        unvalidated cache, self.purgatory. This will also add any computed parent
        hashes recursively. If the hash makes it into the validated tree, this
        will also check the nephews of this hash to see if they can now be
        validated. However, direct descendants will not be checked, and must be
        checked by the caller.
        """
        if type(hash) == long:
            hash = util.ser_uint256(hash)

        key = (level, index)
        if not locked:
            self.rwlock.acquire_write(
            )  # this might benefit from more fine-grained locks when the switch is made to C++
        if key in self.purgatory:
            if self.purgatory[key] == hash:
                if not locked: self.rwlock.release_write()
                return
            else:
                oldpeer = self.peerorigins[self.purgatory[
                    key]] if self.purgatory[key] in self.peerorigins else None
                debuglog(
                    'btnet',
                    'Warning: received two different hashes for the same part of a tree. Replacing old hash.'
                )
                debuglog(
                    'btnet',
                    'Cause is likely either network corruption or a malicious peer. Peers:'
                )
                debuglog('btnet', oldpeer, peer)
                debuglog(
                    'btnet', 'Hash added is (%i, %i): %s. Oldhash: %s.' %
                    (level, index, to_hex(hash), to_hex(self.purgatory[key])))
                # fixme: peer banning
                # continue to add the new hash and validate
        elif self.getnode(level, index, locked=True):
            debuglog(
                'bttree',
                'Debug warning: level=%i index=%i already validated in tree' %
                (level, index))
            if not locked: self.rwlock.release_write()
            return
        self.purgatory[key] = hash
        #self.peerorigins[hash] = peer # fixme: make sure memory growth is bounded

        parent = self.getnode(level - 1, index // 2,
                              locked=True)  # is our parent already valid?
        siblingkey = (level, index ^ 1)

        if not siblingkey in self.purgatory:  # Is this is the right edge of the tree?
            if not index & 1:  # if even (left sibling)
                if self.txcount:
                    height = int(math.ceil(math.log(self.txcount, 2)))
                    assert level <= height
                    edge = (self.txcount - 1) >> (height - level)
                    if index == edge:
                        self.purgatory[
                            siblingkey] = hash  # this can be overwritten later

        if siblingkey in self.purgatory:  # then we can check one level up
            sib = self.purgatory[siblingkey]
            parenthash = self.calcparent(sib, hash) if (
                index %
                2) else self.calcparent(hash, sib)  # left sibling goes first
            if parent and parent == parenthash:
                result = 'connected'
            elif parent and parent != parenthash and not sib == hash:
                debuglog(
                    'btnet',
                    'Invalid hash(es) encountered when checking (%i, %i): %s.'
                    % (level, index, to_hex(hash)))
                debuglog(
                    'btnet', 'Parent (%i, %i) = %s not %s' %
                    (level - 1, index // 2, to_hex(parent),
                     to_hex(parenthash)))
                result = 'invalid'
            elif parent and parent != parenthash and sib == hash:
                debuglog(
                    'btnet', 'Found a bad edge: (%i, %i) = %s not %s' %
                    (level - 1, index // 2, to_hex(parent),
                     to_hex(parenthash)))
                result = 'orphan'  # incorrect tx count hint
            else:  # recurse one level up
                result = self.addhash(level - 1,
                                      index // 2,
                                      parenthash,
                                      None,
                                      locked=True)
        else:
            result = 'orphan'

        if result == 'connected':
            self.setnode(level, index, hash, edge=(hash == sib), locked=True)
            self.setnode(level,
                         index ^ 1,
                         sib,
                         edge=(hash == sib),
                         locked=True)
            del self.purgatory[key]
            del self.purgatory[siblingkey]
            if hash == sib and level == self.levels:  # right edge, bottom row
                self.txcount = index | 1  # left sib is the last tx, but we start counting from 0, so we want the right sib's index
            # the recursive caller of addhash will take care of the children of key, but not siblingkey
            if hash != sib:
                self.checkchildren(siblingkey[0], siblingkey[1], locked=True)
        elif result == 'invalid':
            if sib == hash:  # invalid hint about the number of transactions
                debuglog('btnet', 'Invalid txcount? -- %i ' % self.txcount)
                del self.purgatory[max(siblingkey, key)]
                result = 'orphan'
            else:
                for k in key, siblingkey:
                    # fixme: for multi-level recursion, there's a good chance we're deleting the wrong txes.
                    # should we delete all of the descendants of the lowest valid hash to which this resolves?
                    # or should we leave these hashes all in purgatory? or what? who do we ban?
                    debuglog(
                        'btnet',
                        'Invalid hash(es) encountered. Deleting: (%i, %i): %s.'
                        % (k[0], k[1], to_hex(self.purgatory[k])))
                    #del self.purgatory[k]
        elif result == 'orphan':
            pass  # fixme: deal with peer info (and banning) in each of these branches above
        if not locked: self.rwlock.release_write()
        return result
コード例 #19
0
    def fill_from_rpc(self, data, aux_data):
        '''Convert getblocktemplate result into BlockTemplate instance'''

        self.auxs = aux_data
        self.tree, self.merkle_size = util.make_auxpow_tree(aux_data)
        self.aux_targets = [None for i in self.auxs]
        merkle_leaves = [('0' * 64) for x in range(self.merkle_size)]

        for chain in range(len(self.auxs)):
            merkle_index = self.tree[self.auxs[chain]['chainid']]
            merkle_leaves[merkle_index] = self.auxs[chain]['hash']
            target = self.auxs[chain]['target'].decode('hex')[::-1].encode(
                'hex')
            self.aux_targets[chain] = int(target, 16)
            log.info("Merged Chain: %i network difficulty: %s" %
                     (self.auxs[chain]['chainid'],
                      float(util.diff_to_target(self.aux_targets[chain]))))

        self.merkle_hashes = [int(t, 16) for t in merkle_leaves]
        self.mm_data = '\xfa\xbemm' + util.aux_pow_coinbase_type.pack(
            dict(
                merkle_root=util.merkle_hash(self.merkle_hashes),
                size=self.merkle_size,
                nonce=0,
            ))

        txhashes = [None] + [
            util.ser_uint256(int(t['hash'], 16)) for t in data['transactions']
        ]
        mt = merkletree.MerkleTree(txhashes)

        coinbase = CoinbaseTransaction(self.timestamper, self.coinbaser,
                                       data['coinbasevalue'],
                                       data['coinbaseaux']['flags'],
                                       data['height'],
                                       settings.COINBASE_EXTRAS + self.mm_data,
                                       data['curtime'])

        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.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.merkletree = mt
        self.target = util.uint256_from_compact(self.nBits)
        log.info("MainNet Block Height: %i network difficulty: %s" %
                 (self.height, float(util.diff_to_target(self.target))))

        # 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()
コード例 #20
0
    def fill_from_rpc(self, data):
        '''Convert getblocktemplate result into BlockTemplate instance'''

        commitment = None
        nTime = data['curtime'] if data.has_key('curtime') else None

        if settings.COINDAEMON_HAS_SEGWIT:
            txids = []
            hashes = [None] + [
                util.ser_uint256(int(t['hash'], 16))
                for t in data['transactions']
            ]
            try:
                txids = [None] + [
                    util.ser_uint256(int(t['txid'], 16))
                    for t in data['transactions']
                ]
                mt = merkletree.MerkleTree(txids)
            except KeyError:
                mt = merkletree.MerkleTree(hashes)

            wmt = merkletree.MerkleTree(hashes).withFirst(
                binascii.unhexlify(
                    '0000000000000000000000000000000000000000000000000000000000000000'
                ))
            self.witness = SHA256.new(
                SHA256.new(wmt + witness_nonce).digest()).digest()
            commitment = b'\x6a' + struct.pack(
                ">b",
                len(self.witness) +
                len(witness_magic)) + witness_magic + self.witness
            try:
                default_witness = data['default_witness_commitment']
                commitment_check = binascii.unhexlify(default_witness)
                if (commitment != commitment_check):
                    print(
                        "calculated witness does not match supplied one! This block probably will not be accepted!"
                    )
                    commitment = commitment_check
            except KeyError:
                pass
            self.witness = commitment[6:]
        else:
            txhashes = [None] + [
                util.ser_uint256(int(t['hash'], 16))
                for t in data['transactions']
            ]
            mt = merkletree.MerkleTree(txhashes)

        coinbase = CoinbaseTransaction(self.timestamper, self.coinbaser,
                                       data['coinbasevalue'],
                                       data['coinbaseaux']['flags'],
                                       data['height'], commitment,
                                       settings.COINBASE_EXTRAS, nTime)

        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.vtx = [
            coinbase,
        ]

        for tx in data['transactions']:
            t = TxBlob()
            t.deserialize(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()
コード例 #21
0
 def calcparent(self, hash1, hash2):
     if type(hash1) == long:
         hash1 = util.ser_uint256(hash1)
     if type(hash2) == long:
         hash2 = util.ser_uint256(hash2)
     return util.doublesha(hash1 + hash2)
コード例 #22
0
    def addhash(self, level, index, hash, peer=None):
        """
        Adds a hash to either the validated tree (when possible) or to the
        unvalidated cache, self.purgatory. This will also add any computed parent
        hashes recursively. If the hash makes it into the validated tree, this
        will also check the nephews of this hash to see if they can now be
        validated. However, direct descendents will not be checked, and must be
        checked by the caller.
        """
        if type(hash) == long:
            hash = util.ser_uint256(hash)
        key = (level, index)
        if key in self.purgatory:
            if self.purgatory[key] == hash:
                return
            else:
                oldpeer = self.peerorigins[self.purgatory[key]] if self.purgatory[key] in self.peerorigins else None
                debuglog('btnet', 'Warning: received two different hashes for the same part of a tree. Replacing old hash.')
                debuglog('btnet', 'Cause is likely either network corruption or a malicious peer. Peers:')
                debuglog('btnet', oldpeer, peer)
                debuglog('btnet', 'Hash added is (%i, %i): %s. Oldhash: %s.' % (level, index, to_hex(hash), to_hex(self.purgatory[key])))
                # fixme: peer banning
                # continue to add the new hash and validate
        elif self.getnode(level, index):
            debuglog('bttree', 'Debug warning: level=%i index=%i already validated in tree' % (level, index))
            return
        self.purgatory[key] = hash
        #self.peerorigins[hash] = peer # fixme: make sure memory growth is bounded

        parent = self.getnode(level-1, index//2) # is our parent already valid?
        #if parent: print "valid parent of %i,%i is %i,%i:" %(level, index, level-1, index//2), to_hex(parent])
        siblingkey = (level, index ^ 1)

        if not siblingkey in self.purgatory: # Is this is the right edge of the tree?
            if not index & 1: # if even (left sibling)
                for hint in self.txcounthints:
                    height = int(math.ceil(math.log(hint, 2)))
                    if level > height: continue
                    edge = (hint-1) >> (height - level)
                    if index == edge:
                        self.purgatory[siblingkey] = hash # this can be overwritten later
                        break

        if siblingkey in self.purgatory: # then we can check one level up
            sib = self.purgatory[siblingkey]
            parenthash = self.calcparent(sib, hash) if (index%2) else self.calcparent(hash, sib) # left sibling goes first
            if parent and parent == parenthash:
                result = 'connected'
            elif parent and parent != parenthash and not sib == hash:
                debuglog('btnet', 'Invalid hash(es) encountered when checking (%i, %i): %s.' % (level, index, to_hex(hash)))
                debuglog('btnet', 'Parent (%i, %i) = %s not %s' %  (level-1, index//2, to_hex(parent), to_hex(parenthash)))
                result = 'invalid'
            elif parent and parent != parenthash and sib == hash:
                debuglog('btnet', 'Found a bad edge: (%i, %i) = %s not %s' %  (level-1, index//2, to_hex(parent), to_hex(parenthash)))
                result = 'orphan' # incorrect tx count hint
            else: # recurse one level up
                result = self.addhash(level-1, index//2, parenthash, None)
        else:
            result = 'orphan'

        if result == 'connected':
            self.setnode(level, index, hash, edge=(hash==sib))
            self.setnode(level, index^1, sib, edge=(hash==sib))
            del self.purgatory[key]
            del self.purgatory[siblingkey]
            if hash == sib and level == self.levels: # right edge, bottom row
                self.txcount = index|1-1 # left sib's index
            # the recursive caller of addhash will take care of the children of key, but not siblingkey
            self.checkchildren(siblingkey[0], siblingkey[1])
        elif result == 'invalid':
            if sib == hash: # invalid hint about the number of transactions
                debuglog('btnet', 'Invalid txcount hint: %i among ' % hint, self.txcounthints)
                del self.purgatory[max(siblingkey, key)]
                result = 'orphan'
            else:
                for k in key, siblingkey:
                    # fixme: for multi-level recursion, there's a good chance we're deleting the wrong txes.
                    # should we delete all of the decendants of the lowest valid hash to which this resolves?
                    # or should we leave these hashes all in purgatory? or what? who do we ban?
                    debuglog('btnet', 'Invalid hash(es) encountered. Deleting: (%i, %i): %s.' % (k[0], k[1], to_hex(self.purgatory[k])))
                    #del self.purgatory[k]
        elif result == 'orphan':
            pass # fixme: deal with peer info (and banning) in each of these branches above
        return result