mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2026-08-24 10:05:29 -05:00
make sure to pass in the correct previous transaction block height (#20237)
* make sure to pass in the correct previous transaction block height to get_flags_for_height_and_constants() * review comments
This commit is contained in:
@@ -59,7 +59,7 @@ def test_process_fast_forward_spends_nothing_to_do() -> None:
|
||||
original_version = dataclasses.replace(internal_mempool_item)
|
||||
singleton_ff = SingletonFastForward()
|
||||
bundle_coin_spends = singleton_ff.process_fast_forward_spends(
|
||||
mempool_item=internal_mempool_item, height=TEST_HEIGHT, constants=DEFAULT_CONSTANTS
|
||||
mempool_item=internal_mempool_item, prev_tx_height=TEST_HEIGHT, constants=DEFAULT_CONSTANTS
|
||||
)
|
||||
assert singleton_ff == SingletonFastForward()
|
||||
assert bundle_coin_spends == original_version.bundle_coin_spends
|
||||
@@ -91,7 +91,7 @@ def test_process_fast_forward_spends_latest_unspent() -> None:
|
||||
original_version = dataclasses.replace(internal_mempool_item)
|
||||
singleton_ff = SingletonFastForward()
|
||||
bundle_coin_spends = singleton_ff.process_fast_forward_spends(
|
||||
mempool_item=internal_mempool_item, height=TEST_HEIGHT, constants=DEFAULT_CONSTANTS
|
||||
mempool_item=internal_mempool_item, prev_tx_height=TEST_HEIGHT, constants=DEFAULT_CONSTANTS
|
||||
)
|
||||
child_coin = item.bundle_coin_spends[test_coin.name()].additions[0]
|
||||
expected_fast_forward_spends = {
|
||||
|
||||
@@ -28,6 +28,8 @@ def get_name_puzzle_conditions(
|
||||
height: uint32,
|
||||
constants: ConsensusConstants,
|
||||
) -> NPCResult:
|
||||
# TODO: technically, this is supposed to be the previous transaction block
|
||||
# height. But this is just for testing and it seems to be OK for now
|
||||
flags = get_flags_for_height_and_constants(height, constants) | DONT_VALIDATE_SIGNATURE
|
||||
|
||||
if mempool_mode:
|
||||
|
||||
@@ -83,11 +83,11 @@ async def ignore_block_validation(
|
||||
return new_create
|
||||
|
||||
def run_block(
|
||||
block: FullBlock, prev_generators: list[bytes], constants: ConsensusConstants
|
||||
block: FullBlock, prev_generators: list[bytes], prev_tx_height: uint32, constants: ConsensusConstants
|
||||
) -> tuple[Optional[int], Optional[SpendBundleConditions]]:
|
||||
assert block.transactions_generator is not None
|
||||
assert block.transactions_info is not None
|
||||
flags = get_flags_for_height_and_constants(block.height, constants) | DONT_VALIDATE_SIGNATURE
|
||||
flags = get_flags_for_height_and_constants(prev_tx_height, constants) | DONT_VALIDATE_SIGNATURE
|
||||
if block.height >= constants.HARD_FORK_HEIGHT:
|
||||
run_block = run_block_generator2
|
||||
else:
|
||||
|
||||
@@ -274,7 +274,14 @@ class Blockchain:
|
||||
assert block_generator is not None
|
||||
assert block.transactions_info is not None
|
||||
assert block.foliage_transaction_block is not None
|
||||
flags = get_flags_for_height_and_constants(block.height, self.constants)
|
||||
prev_tx_height = pre_sp_tx_block_height(
|
||||
constants=self.constants,
|
||||
blocks=self,
|
||||
prev_b_hash=block.prev_header_hash,
|
||||
sp_index=block.reward_chain_block.signage_point_index,
|
||||
first_in_sub_slot=len(block.finished_sub_slots) > 0,
|
||||
)
|
||||
flags = get_flags_for_height_and_constants(prev_tx_height, self.constants)
|
||||
additions, removals = additions_and_removals(
|
||||
bytes(block.transactions_generator),
|
||||
block_generator.generator_refs,
|
||||
|
||||
@@ -60,11 +60,11 @@ class PreValidationResult(Streamable):
|
||||
|
||||
# this layer of abstraction is here to let wallet tests monkeypatch it
|
||||
def _run_block(
|
||||
block: FullBlock, prev_generators: list[bytes], constants: ConsensusConstants
|
||||
block: FullBlock, prev_generators: list[bytes], prev_tx_height: uint32, constants: ConsensusConstants
|
||||
) -> tuple[Optional[int], Optional[SpendBundleConditions]]:
|
||||
assert block.transactions_generator is not None
|
||||
assert block.transactions_info is not None
|
||||
flags = get_flags_for_height_and_constants(block.height, constants)
|
||||
flags = get_flags_for_height_and_constants(prev_tx_height, constants)
|
||||
if block.height >= constants.HARD_FORK_HEIGHT:
|
||||
run_block = run_block_generator2
|
||||
else:
|
||||
@@ -116,7 +116,14 @@ def _pre_validate_block(
|
||||
uint16(Err.BLOCK_COST_EXCEEDS_MAX.value), None, None, uint32(validation_time * 1000)
|
||||
)
|
||||
|
||||
err, conds = _run_block(block, prev_generators, constants)
|
||||
prev_tx_height = pre_sp_tx_block_height(
|
||||
constants=constants,
|
||||
blocks=blockchain,
|
||||
prev_b_hash=block.prev_header_hash,
|
||||
sp_index=block.reward_chain_block.signage_point_index,
|
||||
first_in_sub_slot=len(block.finished_sub_slots) > 0,
|
||||
)
|
||||
err, conds = _run_block(block, prev_generators, prev_tx_height, constants)
|
||||
|
||||
assert (err is None) != (conds is None)
|
||||
if err is not None:
|
||||
|
||||
@@ -172,7 +172,7 @@ class SingletonFastForward:
|
||||
fast_forward_spends: dict[bytes32, UnspentLineageInfo] = dataclasses.field(default_factory=dict)
|
||||
|
||||
def process_fast_forward_spends(
|
||||
self, *, mempool_item: InternalMempoolItem, height: uint32, constants: ConsensusConstants
|
||||
self, *, mempool_item: InternalMempoolItem, prev_tx_height: uint32, constants: ConsensusConstants
|
||||
) -> dict[bytes32, BundleCoinSpend]:
|
||||
"""
|
||||
Provides the caller with a `bundle_coin_spends` map that has a proper
|
||||
@@ -182,7 +182,7 @@ class SingletonFastForward:
|
||||
Args:
|
||||
mempool_item: The internal mempool item to process
|
||||
constants: needed in order to refresh the mempool item if needed
|
||||
height: needed in order to refresh the mempool item if needed
|
||||
prev_tx_height: needed in order to refresh the mempool item if needed
|
||||
|
||||
Returns:
|
||||
The resulting `bundle_coin_spends` map of coin IDs to coin spends
|
||||
@@ -273,7 +273,7 @@ class SingletonFastForward:
|
||||
try:
|
||||
# Run the new spend bundle to make sure it remains valid. What we
|
||||
# care about here is whether this call throws or not.
|
||||
get_conditions_from_spendbundle(new_sb, mempool_item.conds.cost, constants, height)
|
||||
get_conditions_from_spendbundle(new_sb, mempool_item.conds.cost, constants, prev_tx_height)
|
||||
# get_conditions_from_spendbundle raises a ValueError with an error code
|
||||
except ValueError as e:
|
||||
# Convert that to a ValidationError
|
||||
|
||||
@@ -39,6 +39,7 @@ from chiabip158 import PyBIP158
|
||||
from chia.consensus.block_creation import create_unfinished_block
|
||||
from chia.consensus.blockchain import BlockchainMutexPriority
|
||||
from chia.consensus.generator_tools import get_block_header
|
||||
from chia.consensus.get_block_challenge import pre_sp_tx_block_height
|
||||
from chia.consensus.get_block_generator import get_block_generator
|
||||
from chia.consensus.pot_iterations import calculate_ip_iters, calculate_iterations_quality, calculate_sp_iters
|
||||
from chia.consensus.signage_point import SignagePoint
|
||||
@@ -1274,7 +1275,14 @@ 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"
|
||||
|
||||
flags = get_flags_for_height_and_constants(request.height, self.full_node.constants)
|
||||
prev_tx_height = pre_sp_tx_block_height(
|
||||
constants=self.full_node.constants,
|
||||
blocks=self.full_node.blockchain,
|
||||
prev_b_hash=block.prev_header_hash,
|
||||
sp_index=block.reward_chain_block.signage_point_index,
|
||||
first_in_sub_slot=len(block.finished_sub_slots) > 0,
|
||||
)
|
||||
flags = get_flags_for_height_and_constants(prev_tx_height, self.full_node.constants)
|
||||
additions, removals = await asyncio.get_running_loop().run_in_executor(
|
||||
self.executor,
|
||||
additions_and_removals,
|
||||
|
||||
@@ -24,6 +24,7 @@ from chia_rs.sized_bytes import bytes32
|
||||
from chia_rs.sized_ints import uint32, uint64, uint128
|
||||
|
||||
from chia.consensus.blockchain import Blockchain, BlockchainMutexPriority
|
||||
from chia.consensus.get_block_challenge import pre_sp_tx_block_height
|
||||
from chia.consensus.get_block_generator import get_block_generator
|
||||
from chia.consensus.pos_quality import UI_ACTUAL_SPACE_CONSTANT_FACTOR
|
||||
from chia.full_node.fee_estimator_interface import FeeEstimatorInterface
|
||||
@@ -489,7 +490,14 @@ class FullNodeRpcApi:
|
||||
if block_generator is None: # if block is not a transaction block.
|
||||
return {"block_spends": []}
|
||||
|
||||
flags = get_flags_for_height_and_constants(full_block.height, self.service.constants)
|
||||
prev_tx_height = pre_sp_tx_block_height(
|
||||
constants=self.service.constants,
|
||||
blocks=self.service.blockchain,
|
||||
prev_b_hash=full_block.prev_header_hash,
|
||||
sp_index=full_block.reward_chain_block.signage_point_index,
|
||||
first_in_sub_slot=len(full_block.finished_sub_slots) > 0,
|
||||
)
|
||||
flags = get_flags_for_height_and_constants(prev_tx_height, self.service.constants)
|
||||
spends = await asyncio.get_running_loop().run_in_executor(
|
||||
self.executor,
|
||||
get_spends_for_trusted_block,
|
||||
@@ -513,7 +521,14 @@ class FullNodeRpcApi:
|
||||
if block_generator is None: # if block is not a transaction block.
|
||||
return {"block_spends_with_conditions": []}
|
||||
|
||||
flags = get_flags_for_height_and_constants(full_block.height, self.service.constants)
|
||||
prev_tx_height = pre_sp_tx_block_height(
|
||||
constants=self.service.constants,
|
||||
blocks=self.service.blockchain,
|
||||
prev_b_hash=full_block.prev_header_hash,
|
||||
sp_index=full_block.reward_chain_block.signage_point_index,
|
||||
first_in_sub_slot=len(full_block.finished_sub_slots) > 0,
|
||||
)
|
||||
flags = get_flags_for_height_and_constants(prev_tx_height, self.service.constants)
|
||||
spends_with_conditions = await asyncio.get_running_loop().run_in_executor(
|
||||
self.executor,
|
||||
get_spends_for_trusted_block_with_conditions,
|
||||
@@ -792,12 +807,19 @@ class FullNodeRpcApi:
|
||||
assert block_generator is not None
|
||||
|
||||
try:
|
||||
prev_tx_height = pre_sp_tx_block_height(
|
||||
constants=self.service.constants,
|
||||
blocks=self.service.blockchain,
|
||||
prev_b_hash=block.prev_header_hash,
|
||||
sp_index=block.reward_chain_block.signage_point_index,
|
||||
first_in_sub_slot=len(block.finished_sub_slots) > 0,
|
||||
)
|
||||
puzzle, solution = get_puzzle_and_solution_for_coin(
|
||||
block_generator.program,
|
||||
block_generator.generator_refs,
|
||||
self.service.constants.MAX_BLOCK_COST_CLVM,
|
||||
coin_record.coin,
|
||||
get_flags_for_height_and_constants(block.height, self.service.constants),
|
||||
get_flags_for_height_and_constants(prev_tx_height, self.service.constants),
|
||||
)
|
||||
return {"coin_solution": CoinSpend(coin_record.coin, puzzle, solution)}
|
||||
except Exception as e:
|
||||
|
||||
+10
-10
@@ -505,15 +505,15 @@ class Mempool:
|
||||
def create_block_generator(
|
||||
self,
|
||||
constants: ConsensusConstants,
|
||||
height: uint32,
|
||||
prev_tx_height: uint32,
|
||||
timeout: float,
|
||||
) -> Optional[NewBlockGenerator]:
|
||||
"""
|
||||
height is needed in case we fast-forward a transaction and we need to
|
||||
re-run its puzzle.
|
||||
prev_tx_height is needed in case we fast-forward a transaction and we
|
||||
need to re-run its puzzle.
|
||||
"""
|
||||
|
||||
mempool_bundle = self.create_bundle_from_mempool_items(constants, height, timeout)
|
||||
mempool_bundle = self.create_bundle_from_mempool_items(constants, prev_tx_height, timeout)
|
||||
if mempool_bundle is None:
|
||||
return None
|
||||
|
||||
@@ -535,7 +535,7 @@ class Mempool:
|
||||
f"spends: {len(removals)} additions: {len(additions)}",
|
||||
)
|
||||
|
||||
flags = get_flags_for_height_and_constants(height, constants) | MEMPOOL_MODE | DONT_VALIDATE_SIGNATURE
|
||||
flags = get_flags_for_height_and_constants(prev_tx_height, constants) | MEMPOOL_MODE | DONT_VALIDATE_SIGNATURE
|
||||
|
||||
err, conds = run_block_generator2(
|
||||
block_program,
|
||||
@@ -551,7 +551,7 @@ class Mempool:
|
||||
if err is not None: # pragma: no cover
|
||||
log.error(
|
||||
f"Failed to compute block cost during farming: {err} "
|
||||
f"height: {height} "
|
||||
f"prev-tx-height: {prev_tx_height} "
|
||||
f"generator: {bytes(block_program).hex()}"
|
||||
)
|
||||
return None
|
||||
@@ -570,7 +570,7 @@ class Mempool:
|
||||
)
|
||||
|
||||
def create_bundle_from_mempool_items(
|
||||
self, constants: ConsensusConstants, height: uint32, timeout: float = 1.0
|
||||
self, constants: ConsensusConstants, prev_tx_height: uint32, timeout: float = 1.0
|
||||
) -> Optional[tuple[SpendBundle, list[Coin]]]:
|
||||
cost_sum = 0 # Checks that total cost does not exceed block maximum
|
||||
fee_sum = 0 # Checks that total fees don't exceed 64 bits
|
||||
@@ -624,7 +624,7 @@ class Mempool:
|
||||
cost_saving = 0
|
||||
else:
|
||||
bundle_coin_spends = singleton_ff.process_fast_forward_spends(
|
||||
mempool_item=item, height=height, constants=constants
|
||||
mempool_item=item, prev_tx_height=prev_tx_height, constants=constants
|
||||
)
|
||||
unique_coin_spends, cost_saving, unique_additions = dedup_coin_spends.get_deduplication_info(
|
||||
bundle_coin_spends=bundle_coin_spends
|
||||
@@ -687,7 +687,7 @@ class Mempool:
|
||||
return agg, additions
|
||||
|
||||
def create_block_generator2(
|
||||
self, constants: ConsensusConstants, height: uint32, timeout: float
|
||||
self, constants: ConsensusConstants, prev_tx_height: uint32, timeout: float
|
||||
) -> Optional[NewBlockGenerator]:
|
||||
fee_sum = 0 # Checks that total fees don't exceed 64 bits
|
||||
additions: list[Coin] = []
|
||||
@@ -723,7 +723,7 @@ class Mempool:
|
||||
assert item.conds is not None
|
||||
cost = item.conds.condition_cost + item.conds.execution_cost
|
||||
bundle_coin_spends = singleton_ff.process_fast_forward_spends(
|
||||
mempool_item=item, height=height, constants=constants
|
||||
mempool_item=item, prev_tx_height=prev_tx_height, constants=constants
|
||||
)
|
||||
unique_coin_spends, cost_saving, unique_additions = dedup_coin_spends.get_deduplication_info(
|
||||
bundle_coin_spends=bundle_coin_spends
|
||||
|
||||
@@ -307,6 +307,8 @@ class MempoolManager:
|
||||
# cache of MempoolItems with height conditions making them not valid yet
|
||||
_pending_cache: PendingTxCache
|
||||
seen_cache_size: int
|
||||
# the peak is only ever set to a transaction block. We use it to validate
|
||||
# timelocks against, so it must have a timestamp.
|
||||
peak: Optional[BlockRecordProtocol]
|
||||
mempool: Mempool
|
||||
_worker_queue_size: int
|
||||
|
||||
Reference in New Issue
Block a user