Add support for pending transactions to get_mempool_item_by_tx_id() #9443 (#13976)

Co-authored-by: russ <2751728+rwarren@users.noreply.github.com>
Co-authored-by: Earle Lowe <30607889+emlowe@users.noreply.github.com>
This commit is contained in:
William Allen 2022-11-22 15:44:11 -06:00 committed by GitHub
parent ca536d7002
commit a825e15a09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 8 deletions

View File

@ -553,11 +553,17 @@ class MempoolManager:
return self.mempool.spends[bundle_hash].spend_bundle
return None
def get_mempool_item(self, bundle_hash: bytes32) -> Optional[MempoolItem]:
"""Returns a MempoolItem if it's inside one the mempools"""
if bundle_hash in self.mempool.spends:
return self.mempool.spends[bundle_hash]
return None
def get_mempool_item(self, bundle_hash: bytes32, include_pending: bool = False) -> Optional[MempoolItem]:
"""
Returns a MempoolItem if it's inside one the mempools.
If include_pending is specified, also check the PENDING cache.
"""
item = self.mempool.spends.get(bundle_hash, None)
if not item and include_pending:
# no async lock needed since we're not mutating the potential_cache
item = self.potential_cache._txs.get(bundle_hash, None)
return item
async def new_peak(
self, new_peak: Optional[BlockRecord], last_npc_result: Optional[NPCResult]

View File

@ -747,9 +747,10 @@ class FullNodeRpcApi:
async def get_mempool_item_by_tx_id(self, request: Dict) -> EndpointResult:
if "tx_id" not in request:
raise ValueError("No tx_id in request")
include_pending: bool = request.get("include_pending", False)
tx_id: bytes32 = bytes32.from_hexstr(request["tx_id"])
item = self.service.mempool_manager.get_mempool_item(tx_id)
item = self.service.mempool_manager.get_mempool_item(tx_id, include_pending)
if item is None:
raise ValueError(f"Tx id 0x{tx_id.hex()} not in the mempool")

View File

@ -231,9 +231,11 @@ class FullNodeRpcClient(RpcClient):
converted[bytes32(hexstr_to_bytes(tx_id_hex))] = item
return converted
async def get_mempool_item_by_tx_id(self, tx_id: bytes32) -> Optional[Dict]:
async def get_mempool_item_by_tx_id(self, tx_id: bytes32, include_pending: bool = False) -> Optional[Dict]:
try:
response = await self.fetch("get_mempool_item_by_tx_id", {"tx_id": tx_id.hex()})
response = await self.fetch(
"get_mempool_item_by_tx_id", {"tx_id": tx_id.hex(), "include_pending": include_pending}
)
return response["mempool_item"]
except Exception:
return None

View File

@ -5,6 +5,7 @@ from typing import List
import pytest
from blspy import AugSchemeMPL
from clvm.casts import int_to_bytes
from chia.consensus.pot_iterations import is_overflow_block
from chia.full_node.signage_point import SignagePoint
@ -15,6 +16,8 @@ from chia.simulator.block_tools import get_signage_point, test_constants
from chia.simulator.simulator_protocol import FarmNewBlockProtocol, ReorgProtocol
from chia.simulator.time_out_assert import time_out_assert
from chia.simulator.wallet_tools import WalletTool
from chia.types.condition_opcodes import ConditionOpcode
from chia.types.condition_with_args import ConditionWithArgs
from chia.types.full_block import FullBlock
from chia.types.spend_bundle import SpendBundle
from chia.types.unfinished_block import UnfinishedBlock
@ -137,6 +140,7 @@ class TestRpc:
assert len(await client.get_all_mempool_items()) == 0
assert len(await client.get_all_mempool_tx_ids()) == 0
assert (await client.get_mempool_item_by_tx_id(spend_bundle.name())) is None
assert (await client.get_mempool_item_by_tx_id(spend_bundle.name(), False)) is None
await client.push_tx(spend_bundle)
coin = spend_bundle.additions()[0]
@ -156,6 +160,27 @@ class TestRpc:
)
assert (await client.get_coin_record_by_name(coin.name())) is None
# Verify that the include_pending arg to get_mempool_item_by_tx_id works
coin_to_spend_pending = list(blocks[-1].get_included_reward_coins())[1]
ahr = ConditionOpcode.ASSERT_HEIGHT_RELATIVE # to force pending/potential
condition_dic = {ahr: [ConditionWithArgs(ahr, [int_to_bytes(100)])]}
spend_bundle_pending = wallet.generate_signed_transaction(
coin_to_spend_pending.amount,
ph_receiver,
coin_to_spend_pending,
condition_dic=condition_dic,
)
await client.push_tx(spend_bundle_pending)
assert (
await client.get_mempool_item_by_tx_id(spend_bundle_pending.name(), False)
) is None # not strictly in the mempool
assert (
SpendBundle.from_json_dict(
(await client.get_mempool_item_by_tx_id(spend_bundle_pending.name(), True))["spend_bundle"]
)
== spend_bundle_pending # pending entry into mempool, so include_pending fetches
)
await full_node_api_1.farm_new_transaction_block(FarmNewBlockProtocol(ph_2))
coin_record = await client.get_coin_record_by_name(coin.name())