Exemple #1
0
    def add_block(self, block, forward_pending_transactions=True):
        "returns True if block was added sucessfully"
        _log = log.bind(block_hash=block)
        # make sure we know the parent
        if not block.has_parent() and not block.is_genesis():
            _log.debug('missing parent')
            return False

        if not block.validate_uncles():
            _log.debug('invalid uncles')
            return False

        if not len(block.nonce) == 8:
            _log.debug('nonce not set')
            return False
        elif not block.header.check_pow(nonce=block.nonce) and\
                not block.is_genesis():
            _log.debug('invalid nonce')
            return False

        if block.has_parent():
            try:
                processblock.verify(block, block.get_parent())
            except processblock.VerificationFailed as e:
                _log.critical('VERIFICATION FAILED', error=e)
                f = os.path.join(utils.data_dir, 'badblock.log')
                open(f, 'w').write(to_string(block.hex_serialize()))
                return False

        if block.number < self.head.number:
            _log.debug("older than head", head_hash=self.head)
            # Q: Should we have any limitations on adding blocks?

        self.index.add_block(block)
        self._store_block(block)

        # set to head if this makes the longest chain w/ most work for that number
        if block.chain_difficulty() > self.head.chain_difficulty():
            _log.debug('new head')
            self._update_head(block, forward_pending_transactions)
        elif block.number > self.head.number:
            _log.warn('has higher blk number than head but lower chain_difficulty',
                      head_hash=self.head, block_difficulty=block.chain_difficulty(),
                      head_difficulty=self.head.chain_difficulty())
        block.transactions.clear_all()
        block.receipts.clear_all()
        block.state.db.commit_refcount_changes(block.number)
        block.state.db.cleanup(block.number)
        self.commit()  # batch commits all changes that came with the new block
        return True
Exemple #2
0
 def _update_head(self, block, forward_pending_transactions=True):
     success = True
     reverted_blocks = []
     if block.number > 0:
         b = block.get_parent()
         h = self.head
         b_children = []
         if b.hash != h.hash:
             log_chain.warn('reverting')
             # revert head back to number of block.parent
             while h.number > b.number:
                 reverted_blocks.append(h)
                 h = h.get_parent()
             # if b's parent is ahead of head
             while b.number > h.number:
                 b_children.append(b)
                 b = b.get_parent()
             # b & h now have same number, wind back one at a time until
             # hashes match
             while b.hash != h.hash:
                 reverted_blocks.append(h)
                 h = h.get_parent()
                 b_children.append(b)
                 b = b.get_parent()
             for bc in b_children:
                 success = success and verify(bc, bc.get_parent())
     super(Chain, self)._update_head(block, forward_pending_transactions)
     # revert the db after chain.head is updated
     if success and reverted_blocks and self.revert_block_cb:
         self.revert_block_cb(reverted_blocks)
Exemple #3
0
 def _update_head(self, block, forward_pending_transactions=True):
     log.debug('updating head')
     if not block.is_genesis():
         #assert self.head.chain_difficulty() < block.chain_difficulty()
         if block.get_parent() != self.head:
             log.debug('New Head is on a different branch',
                       head_hash=block,
                       old_head_hash=self.head)
     # Some temporary auditing to make sure pruning is working well
     if block.number > 0 and block.number % 500 == 0 and isinstance(
             self.db, RefcountDB):
         trie.proof.push(trie.RECORDING)
         block.to_dict(with_state=True)
         n = trie.proof.get_nodelist()
         trie.proof.pop()
         # log.debug('State size: %d\n' % sum([(len(rlp.encode(a)) + 32) for a in n]))
     # Fork detected, revert death row and change logs
     if block.number > 0:
         b = block.get_parent()
         h = self.head
         b_children = []
         if b.hash != h.hash:
             log.warn('reverting')
             while h.number > b.number:
                 h.state.db.revert_refcount_changes(h.number)
                 h = h.get_parent()
             while b.number > h.number:
                 b_children.append(b)
                 b = b.get_parent()
             while b.hash != h.hash:
                 h.state.db.revert_refcount_changes(h.number)
                 h = h.get_parent()
                 b_children.append(b)
                 b = b.get_parent()
             for bc in b_children:
                 processblock.verify(bc, bc.get_parent())
     self.blockchain.put('HEAD', block.hash)
     assert self.blockchain.get('HEAD') == block.hash
     self.index.update_blocknumbers(self.head)
     assert self.head == block
     log.debug('set new head', head=self.head)
     self._update_head_candidate(forward_pending_transactions)
     if self.new_head_cb and not block.is_genesis():
         self.new_head_cb(block)
Exemple #4
0
 def _update_head(self, block, forward_pending_transactions=True):
     log.debug('updating head')
     if not block.is_genesis():
         #assert self.head.chain_difficulty() < block.chain_difficulty()
         if block.get_parent() != self.head:
             log.debug('New Head is on a different branch',
                       head_hash=block, old_head_hash=self.head)
     # Some temporary auditing to make sure pruning is working well
     if block.number > 0 and block.number % 500 == 0 and isinstance(self.db, RefcountDB):
         trie.proof.push(trie.RECORDING)
         block.to_dict(with_state=True)
         n = trie.proof.get_nodelist()
         trie.proof.pop()
         # log.debug('State size: %d\n' % sum([(len(rlp.encode(a)) + 32) for a in n]))
     # Fork detected, revert death row and change logs
     if block.number > 0:
         b = block.get_parent()
         h = self.head
         b_children = []
         if b.hash != h.hash:
             log.warn('reverting')
             while h.number > b.number:
                 h.state.db.revert_refcount_changes(h.number)
                 h = h.get_parent()
             while b.number > h.number:
                 b_children.append(b)
                 b = b.get_parent()
             while b.hash != h.hash:
                 h.state.db.revert_refcount_changes(h.number)
                 h = h.get_parent()
                 b_children.append(b)
                 b = b.get_parent()
             for bc in b_children:
                 processblock.verify(bc, bc.get_parent())
     self.blockchain.put('HEAD', block.hash)
     assert self.blockchain.get('HEAD') == block.hash
     self.index.update_blocknumbers(self.head)
     assert self.head == block
     log.debug('set new head', head=self.head)
     self._update_head_candidate(forward_pending_transactions)
     if self.new_head_cb and not block.is_genesis():
         self.new_head_cb(block)