diff --git a/chia/full_node/mempool.py b/chia/full_node/mempool.py index 116a509538a0..909e87308ff6 100644 --- a/chia/full_node/mempool.py +++ b/chia/full_node/mempool.py @@ -184,32 +184,33 @@ class Mempool: items.extend(self._row_to_item(row) for row in cursor) return items - def get_min_fee_rate(self, cost: int) -> float: + def get_min_fee_rate(self, cost: int) -> Optional[float]: """ Gets the minimum fpc rate that a transaction with specified cost will need in order to get included. """ - if self.at_full_capacity(cost): - # TODO: make MempoolItem.cost be CLVMCost - current_cost = int(self.total_mempool_cost()) + if not self.at_full_capacity(cost): + return 0 - # Iterates through all spends in increasing fee per cost - with self._db_conn: - cursor = self._db_conn.execute("SELECT cost,fee_per_cost FROM tx ORDER BY fee_per_cost ASC, seq DESC") + # TODO: make MempoolItem.cost be CLVMCost + current_cost = int(self.total_mempool_cost()) - item_cost: int - fee_per_cost: float - for item_cost, fee_per_cost in cursor: - current_cost -= item_cost - # Removing one at a time, until our transaction of size cost fits - if current_cost + cost <= self.mempool_info.max_size_in_cost: - return fee_per_cost + # Iterates through all spends in increasing fee per cost + with self._db_conn: + cursor = self._db_conn.execute("SELECT cost,fee_per_cost FROM tx ORDER BY fee_per_cost ASC, seq DESC") - raise ValueError( + item_cost: int + fee_per_cost: float + for item_cost, fee_per_cost in cursor: + current_cost -= item_cost + # Removing one at a time, until our transaction of size cost fits + if current_cost + cost <= self.mempool_info.max_size_in_cost: + return fee_per_cost + + log.info( f"Transaction with cost {cost} does not fit in mempool of max cost {self.mempool_info.max_size_in_cost}" ) - else: - return 0 + return None def new_tx_block(self, block_height: uint32, timestamp: uint64) -> None: """ diff --git a/chia/full_node/mempool_manager.py b/chia/full_node/mempool_manager.py index c106fe15bf2b..c41e415e4e15 100644 --- a/chia/full_node/mempool_manager.py +++ b/chia/full_node/mempool_manager.py @@ -244,11 +244,12 @@ class MempoolManager: if cost == 0: return False fees_per_cost = fees / cost - if not self.mempool.at_full_capacity(cost) or ( - fees_per_cost >= self.nonzero_fee_minimum_fpc and fees_per_cost > self.mempool.get_min_fee_rate(cost) - ): + if not self.mempool.at_full_capacity(cost): return True - return False + if fees_per_cost < self.nonzero_fee_minimum_fpc: + return False + min_fee_rate = self.mempool.get_min_fee_rate(cost) + return min_fee_rate is not None and fees_per_cost > min_fee_rate def add_and_maybe_pop_seen(self, spend_name: bytes32) -> None: self.seen_bundle_hashes[spend_name] = spend_name @@ -465,8 +466,12 @@ class MempoolManager: if self.mempool.at_full_capacity(cost): if fees_per_cost < self.nonzero_fee_minimum_fpc: return Err.INVALID_FEE_TOO_CLOSE_TO_ZERO, None, [] - if fees_per_cost <= self.mempool.get_min_fee_rate(cost): + min_fee_rate = self.mempool.get_min_fee_rate(cost) + if min_fee_rate is None: + return Err.INVALID_COST_RESULT, None, [] + if fees_per_cost <= min_fee_rate: return Err.INVALID_FEE_LOW_FEE, None, [] + # Check removals against UnspentDB + DiffStore + Mempool + SpendBundle # Use this information later when constructing a block fail_reason, conflicts = self.check_removals(non_eligible_coin_ids, removal_record_dict) diff --git a/tests/core/mempool/test_mempool.py b/tests/core/mempool/test_mempool.py index 297555951c47..550305cde0f7 100644 --- a/tests/core/mempool/test_mempool.py +++ b/tests/core/mempool/test_mempool.py @@ -310,8 +310,7 @@ class TestMempool: mempool = Mempool(mempool_info, fee_estimator) assert mempool.get_min_fee_rate(104000) == 0 - with pytest.raises(ValueError): - mempool.get_min_fee_rate(max_mempool_cost + 1) + assert mempool.get_min_fee_rate(max_mempool_cost + 1) is None coin = await next_block(full_node_1, wallet_a, bt) spend_bundle = generate_test_spend_bundle(wallet_a, coin)