Additions removals (#18741)

* use additions_and_removals() in the request_block_header() full node API. This is slightly faster, and untangles it from the function used for consensus

* use additions_and_removals() instead of get_name_puzzle_conditions() in run_one_block(). We've already validated the block, we just need to recompute the additions and removals
This commit is contained in:
Arvid Norberg
2024-10-22 12:15:07 -07:00
committed by GitHub
parent a80d779fe6
commit 45b08d60e3
3 changed files with 61 additions and 25 deletions
+30
View File
@@ -111,6 +111,36 @@ class ForkInfo:
assert coin.name() not in self.additions_since_fork
self.additions_since_fork[coin.name()] = ForkAdd(coin, block.height, timestamp, None, True)
def include_block(
self,
additions: list[tuple[Coin, Optional[bytes]]],
removals: list[Coin],
block: FullBlock,
header_hash: bytes32,
) -> None:
height = block.height
assert self.peak_height == height - 1
assert len(self.block_hashes) == self.peak_height - self.fork_height
assert block.height == self.fork_height + 1 + len(self.block_hashes)
self.block_hashes.append(header_hash)
self.peak_height = int(block.height)
self.peak_hash = header_hash
if block.foliage_transaction_block is not None:
timestamp = block.foliage_transaction_block.timestamp
for spend in removals:
self.removals_since_fork[bytes32(spend.name())] = ForkRem(bytes32(spend.puzzle_hash), height)
for coin, hint in additions:
self.additions_since_fork[coin.name()] = ForkAdd(coin, height, timestamp, hint, False)
for coin in block.get_included_reward_coins():
assert block.foliage_transaction_block is not None
timestamp = block.foliage_transaction_block.timestamp
assert coin.name() not in self.additions_since_fork
self.additions_since_fork[coin.name()] = ForkAdd(coin, block.height, timestamp, None, True)
def rollback(self, header_hash: bytes32, height: int) -> None:
assert height <= self.peak_height
self.peak_height = height
+10 -11
View File
@@ -10,7 +10,7 @@ from enum import Enum
from pathlib import Path
from typing import TYPE_CHECKING, ClassVar, Optional, cast
from chia_rs import BLSCache
from chia_rs import BLSCache, additions_and_removals, get_flags_for_height_and_constants
from chia.consensus.block_body_validation import ForkInfo, validate_block_body
from chia.consensus.block_header_validation import validate_unfinished_header_block
@@ -25,7 +25,6 @@ from chia.consensus.multiprocess_validation import PreValidationResult
from chia.full_node.block_height_map import BlockHeightMap
from chia.full_node.block_store import BlockStore
from chia.full_node.coin_store import CoinStore
from chia.full_node.mempool_check_conditions import get_name_puzzle_conditions
from chia.types.blockchain_format.coin import Coin
from chia.types.blockchain_format.sized_bytes import bytes32
from chia.types.blockchain_format.sub_epoch_summary import SubEpochSummary
@@ -259,22 +258,22 @@ class Blockchain:
assert fork_info.peak_height == block.height - 1
assert block.height == 0 or fork_info.peak_hash == block.prev_header_hash
npc: Optional[NPCResult] = None
additions: list[tuple[Coin, Optional[bytes]]] = []
removals: list[Coin] = []
if block.transactions_generator is not None:
block_generator: Optional[BlockGenerator] = await get_block_generator(self.lookup_block_generators, block)
assert block_generator is not None
assert block.transactions_info is not None
assert block.foliage_transaction_block is not None
npc = get_name_puzzle_conditions(
block_generator,
block.transactions_info.cost,
mempool_mode=False,
height=block.height,
constants=self.constants,
flags = get_flags_for_height_and_constants(block.height, self.constants)
additions, removals = additions_and_removals(
bytes(block.transactions_generator),
block_generator.generator_refs,
flags,
self.constants,
)
assert npc.error is None
fork_info.include_spends(None if npc is None else npc.conds, block, block.header_hash)
fork_info.include_block(additions, removals, block, block.header_hash)
async def add_block(
self,
+21 -14
View File
@@ -1,7 +1,6 @@
from __future__ import annotations
import asyncio
import functools
import logging
import time
import traceback
@@ -10,7 +9,14 @@ from datetime import datetime, timezone
from typing import TYPE_CHECKING, Optional, cast
import anyio
from chia_rs import AugSchemeMPL, G1Element, G2Element, MerkleSet
from chia_rs import (
AugSchemeMPL,
G1Element,
G2Element,
MerkleSet,
additions_and_removals,
get_flags_for_height_and_constants,
)
from chiabip158 import PyBIP158
from chia.consensus.block_creation import create_unfinished_block
@@ -22,7 +28,7 @@ from chia.full_node.bundle_tools import simple_solution_generator, simple_soluti
from chia.full_node.coin_store import CoinStore
from chia.full_node.fee_estimate import FeeEstimate, FeeEstimateGroup, fee_rate_v2_to_v1
from chia.full_node.fee_estimator_interface import FeeEstimatorInterface
from chia.full_node.mempool_check_conditions import get_name_puzzle_conditions, get_puzzle_and_solution_for_coin
from chia.full_node.mempool_check_conditions import get_puzzle_and_solution_for_coin
from chia.full_node.signage_point import SignagePoint
from chia.full_node.tx_processing_queue import TransactionQueueFull
from chia.protocols import farmer_protocol, full_node_protocol, introducer_protocol, timelord_protocol, wallet_protocol
@@ -62,7 +68,7 @@ from chia.util.api_decorators import api_request
from chia.util.batches import to_batches
from chia.util.db_wrapper import SQLITE_MAX_VARIABLE_NUMBER
from chia.util.full_block_utils import header_block_from_block
from chia.util.generator_tools import get_block_header, tx_removals_and_additions
from chia.util.generator_tools import get_block_header
from chia.util.hash import std_hash
from chia.util.ints import uint8, uint32, uint64, uint128
from chia.util.limited_semaphore import LimitedSemaphoreFullError
@@ -1195,19 +1201,20 @@ class FullNodeAPI:
# transactions_generator, so the block_generator should always be set
assert block_generator is not None, "failed to get block_generator for tx-block"
npc_result = await asyncio.get_running_loop().run_in_executor(
flags = get_flags_for_height_and_constants(request.height, self.full_node.constants)
additions, removals = await asyncio.get_running_loop().run_in_executor(
self.executor,
functools.partial(
get_name_puzzle_conditions,
block_generator,
self.full_node.constants.MAX_BLOCK_COST_CLVM,
mempool_mode=False,
height=request.height,
constants=self.full_node.constants,
),
additions_and_removals,
bytes(block.transactions_generator),
block_generator.generator_refs,
flags,
self.full_node.constants,
)
# strip the hint from additions, and compute the puzzle hash for
# removals
tx_additions = [add[0] for add in additions]
tx_removals = [rem.name() for rem in removals]
tx_removals, tx_additions = tx_removals_and_additions(npc_result.conds)
header_block = get_block_header(block, tx_additions, tx_removals)
msg = make_msg(
ProtocolMessageTypes.respond_block_header,