Example #1
0
    async def add_full_block(self, block: FullBlock, sub_block: SubBlockRecord) -> None:

        cursor_1 = await self.db.execute(
            "INSERT OR REPLACE INTO full_blocks VALUES(?, ?, ?, ?, ?)",
            (
                block.header_hash.hex(),
                sub_block.height,
                block.sub_block_height,
                int(block.is_block()),
                bytes(block),
            ),
        )

        await cursor_1.close()

        cursor_2 = await self.db.execute(
            "INSERT OR REPLACE INTO sub_block_records VALUES(?, ?, ?, ?, ?, ?)",
            (
                block.header_hash.hex(),
                block.prev_header_hash.hex(),
                block.sub_block_height,
                bytes(sub_block),
                False,
                block.is_block(),
            ),
        )
        await cursor_2.close()
        await self.db.commit()
    async def add_full_block(self, block: FullBlock,
                             sub_block: SubBlockRecord) -> None:
        self.block_cache.put(block.header_hash, block)
        cursor_1 = await self.db.execute(
            "INSERT OR REPLACE INTO full_blocks VALUES(?, ?, ?, ?)",
            (
                block.header_hash.hex(),
                block.height,
                int(block.is_block()),
                bytes(block),
            ),
        )

        await cursor_1.close()

        cursor_2 = await self.db.execute(
            "INSERT OR REPLACE INTO block_records VALUES(?, ?, ?, ?,?, ?, ?)",
            (
                block.header_hash.hex(),
                block.prev_header_hash.hex(),
                block.height,
                bytes(sub_block),
                None if sub_block.sub_epoch_summary_included is None else
                bytes(sub_block.sub_epoch_summary_included),
                False,
                block.is_block(),
            ),
        )
        await cursor_2.close()
        await self.db.commit()
Example #3
0
def get_future_reward_coins(block: FullBlock) -> Tuple[Coin, Coin]:
    pool_amount = calculate_pool_reward(block.height)
    farmer_amount = calculate_base_farmer_reward(block.height)
    if block.is_block():
        assert block.transactions_info is not None
        farmer_amount = uint64(farmer_amount + block.transactions_info.fees)
    pool_coin: Coin = create_pool_coin(
        block.height,
        block.foliage_sub_block.foliage_sub_block_data.pool_target.puzzle_hash,
        pool_amount,
    )
    farmer_coin: Coin = create_farmer_coin(
        block.height,
        block.foliage_sub_block.foliage_sub_block_data.farmer_reward_puzzle_hash,
        farmer_amount,
    )
    return pool_coin, farmer_coin
Example #4
0
    async def new_block(self, block: FullBlock):
        """
        Only called for sub-blocks which are blocks (and thus have rewards and transactions)
        """
        if block.is_block() is False:
            return
        assert block.foliage_block is not None
        removals, additions = block.tx_removals_and_additions()

        for coin in additions:
            record: CoinRecord = CoinRecord(
                coin,
                block.height,
                uint32(0),
                False,
                False,
                block.foliage_block.timestamp,
            )
            await self._add_coin_record(record)

        for coin_name in removals:
            await self._set_spent(coin_name, block.height)

        included_reward_coins = block.get_included_reward_coins()
        if block.height == 0:
            assert len(included_reward_coins) == 0
        else:
            assert len(included_reward_coins) >= 2

        for coin in included_reward_coins:
            reward_coin_r: CoinRecord = CoinRecord(
                coin,
                block.height,
                uint32(0),
                False,
                True,
                block.foliage_block.timestamp,
            )
            await self._add_coin_record(reward_coin_r)
    async def receive_block(
        self,
        block: FullBlock,
        pre_validation_result: Optional[PreValidationResult] = None,
    ) -> Tuple[ReceiveBlockResult, Optional[Err], Optional[uint32]]:
        """
        This method must be called under the blockchain lock
        Adds a new block into the blockchain, if it's valid and connected to the current
        blockchain, regardless of whether it is the child of a head, or another block.
        Returns a header if block is added to head. Returns an error if the block is
        invalid. Also returns the fork height, in the case of a new peak.
        """
        genesis: bool = block.sub_block_height == 0

        if block.header_hash in self.sub_blocks:
            return ReceiveBlockResult.ALREADY_HAVE_BLOCK, None, None

        if block.prev_header_hash not in self.sub_blocks and not genesis:
            return (
                ReceiveBlockResult.DISCONNECTED_BLOCK,
                Err.INVALID_PREV_BLOCK_HASH,
                None,
            )

        if pre_validation_result is None:
            if block.sub_block_height == 0:
                prev_sb: Optional[SubBlockRecord] = None
            else:
                prev_sb = self.sub_blocks[block.prev_header_hash]
            sub_slot_iters, difficulty = get_sub_slot_iters_and_difficulty(
                self.constants, block, self.sub_height_to_hash, prev_sb,
                self.sub_blocks)
            required_iters, error = validate_finished_header_block(
                self.constants,
                self.sub_blocks,
                block.get_block_header(),
                False,
                difficulty,
                sub_slot_iters,
            )

            if error is not None:
                return ReceiveBlockResult.INVALID_BLOCK, error.code, None
        else:
            required_iters = pre_validation_result.required_iters
            assert pre_validation_result.error is None
        assert required_iters is not None

        error_code = await validate_block_body(
            self.constants,
            self.sub_blocks,
            self.sub_height_to_hash,
            self.block_store,
            self.coin_store,
            self.get_peak(),
            block,
            block.sub_block_height,
            block.height if block.is_block() else None,
            pre_validation_result.cost_result
            if pre_validation_result is not None else None,
        )

        if error_code is not None:
            return ReceiveBlockResult.INVALID_BLOCK, error_code, None

        sub_block = block_to_sub_block_record(
            self.constants,
            self.sub_blocks,
            self.sub_height_to_hash,
            required_iters,
            block,
            None,
        )

        # Always add the block to the database
        await self.block_store.add_full_block(block, sub_block)
        self.sub_blocks[sub_block.header_hash] = sub_block

        fork_height: Optional[uint32] = await self._reconsider_peak(
            sub_block, genesis)
        if fork_height is not None:
            return ReceiveBlockResult.NEW_PEAK, None, fork_height
        else:
            return ReceiveBlockResult.ADDED_AS_ORPHAN, None, None