Example #1
0
    async def submit_work(self, header_hash: bytes, nonce: int, mixhash: bytes) -> bool:
        if not self.remote:
            raise ValueError("Should only be used for remote miner")

        if header_hash not in self.work_map:
            return False
        block = self.work_map[header_hash]
        header = copy.copy(block.header)
        header.nonce, header.mixhash = nonce, mixhash

        # lower the difficulty for root block signed by guardian
        if self.guardian_private_key and isinstance(block, RootBlock):
            diff = Guardian.adjust_difficulty(header.difficulty, header.height)
            try:
                validate_seal(header, self.consensus_type, adjusted_diff=diff)
            except ValueError:
                return False
            # sign as a guardian
            header.sign_with_private_key(self.guardian_private_key)
        else:  # minor block, or doesn't have guardian private key
            try:
                validate_seal(header, self.consensus_type)
            except ValueError:
                return False

        block.header = header  # actual update
        try:
            await self.add_block_async_func(block)
            del self.work_map[header_hash]
            self.current_work = None
            return True
        except Exception as ex:
            Logger.error(ex)
            return False
Example #2
0
    def validate_block_header(self,
                              block_header: RootBlockHeader,
                              block_hash=None):
        """ Validate the block header.
        """
        height = block_header.height
        if height < 1:
            raise ValueError("unexpected height")

        if not self.db.contain_root_block_by_hash(
                block_header.hash_prev_block):
            raise ValueError("previous hash block mismatch")
        prev_block_header = self.db.get_root_block_header_by_hash(
            block_header.hash_prev_block)

        if prev_block_header.height + 1 != height:
            raise ValueError("incorrect block height")

        if (block_header.create_time >
                time_ms() // 1000 + ALLOWED_FUTURE_BLOCKS_TIME_VALIDATION):
            raise ValueError("block too far into future")

        if block_header.create_time <= prev_block_header.create_time:
            raise ValueError(
                "incorrect create time tip time {}, new block time {}".format(
                    block_header.create_time, prev_block_header.create_time))

        if (len(block_header.extra_data) >
                self.env.quark_chain_config.BLOCK_EXTRA_DATA_SIZE_LIMIT):
            raise ValueError("extra_data in block is too large")

        header_hash = block_header.get_hash()
        if block_hash is None:
            block_hash = header_hash

        # Check difficulty, potentially adjusted by guardian mechanism
        adjusted_diff = None  # type: Optional[int]
        if not self.env.quark_chain_config.SKIP_ROOT_DIFFICULTY_CHECK:
            diff = self.diff_calc.calculate_diff_with_parent(
                prev_block_header, block_header.create_time)
            if diff != block_header.difficulty:
                raise ValueError("incorrect difficulty")
            # lower the difficulty for root block signed by guardian
            if block_header.verify_signature(
                    self.env.quark_chain_config.guardian_public_key):
                adjusted_diff = Guardian.adjust_difficulty(
                    diff, block_header.height)

        if (block_header.difficulty + prev_block_header.total_difficulty !=
                block_header.total_difficulty):
            raise ValueError("incorrect total difficulty")

        # Check PoW if applicable
        consensus_type = self.root_config.CONSENSUS_TYPE
        validate_seal(block_header,
                      consensus_type,
                      adjusted_diff=adjusted_diff)

        return block_hash
Example #3
0
        async def add(block_to_add):
            h = block_to_add.header
            diff = h.difficulty

            if h.verify_signature(priv.public_key):
                diff = Guardian.adjust_difficulty(diff, h.height)

            validate_seal(block_to_add.header, doublesha, adjusted_diff=diff)
Example #4
0
    def validate_block_header(self, block_header: RootBlockHeader, block_hash=None):
        """ Validate the block header.
        """
        height = block_header.height
        if height < 1:
            raise ValueError("unexpected height")

        if not self.db.contain_root_block_by_hash(block_header.hash_prev_block):
            raise ValueError("previous hash block mismatch")
        prev_block_header = self.db.get_root_block_header_by_hash(
            block_header.hash_prev_block
        )

        if prev_block_header.height + 1 != height:
            raise ValueError("incorrect block height")

        if block_header.create_time <= prev_block_header.create_time:
            raise ValueError(
                "incorrect create time tip time {}, new block time {}".format(
                    block_header.create_time, prev_block_header.create_time
                )
            )

        if (
            len(block_header.extra_data)
            > self.env.quark_chain_config.BLOCK_EXTRA_DATA_SIZE_LIMIT
        ):
            raise ValueError("extra_data in block is too large")

        header_hash = block_header.get_hash()
        if block_hash is None:
            block_hash = header_hash

        # Check difficulty
        if not self.env.quark_chain_config.SKIP_ROOT_DIFFICULTY_CHECK:
            diff = self.diff_calc.calculate_diff_with_parent(
                prev_block_header, block_header.create_time
            )
            # lower the difficulty for root block signed by guardian
            if block_header.verify_signature(
                self.env.quark_chain_config.guardian_public_key
            ):
                diff = Guardian.adjust_difficulty(diff, block_header.height)
            if diff != block_header.difficulty:
                raise ValueError("incorrect difficulty")

        # Check PoW if applicable
        consensus_type = self.env.quark_chain_config.ROOT.CONSENSUS_TYPE
        validate_seal(block_header, consensus_type)

        return block_hash
Example #5
0
    async def submit_work(self, header_hash: bytes, nonce: int,
                          mixhash: bytes) -> bool:
        if not self.remote:
            raise ValueError("Should only be used for remote miner")

        if header_hash not in self.work_map:
            return False
        # this copy is necessary since there might be multiple submissions concurrently
        block = copy.deepcopy(self.work_map[header_hash])
        header = block.header
        header.nonce, header.mixhash = nonce, mixhash

        # lower the difficulty for root block signed by guardian
        if self.guardian_private_key and isinstance(block, RootBlock):
            diff = Guardian.adjust_difficulty(header.difficulty, header.height)
            try:
                validate_seal(header, self.consensus_type, adjusted_diff=diff)
            except ValueError:
                return False
            # sign as a guardian
            header.sign_with_private_key(self.guardian_private_key)
        else:  # minor block, or doesn't have guardian private key
            try:
                validate_seal(header, self.consensus_type)
            except ValueError:
                return False
        try:
            await self.add_block_async_func(block)
            # a previous submission of the same work could have removed the key
            if header_hash in self.work_map:
                del self.work_map[header_hash]
                self.current_work = None
            return True
        except Exception:
            Logger.error_exception()
            return False