Added get_coin_records_by_parent_id(s) (#7310)

* Added new RPCs to get coins by their parent

* Got rid of the individual request in favor of requiring a list of puzzle hashes
This commit is contained in:
Matt Hauff
2021-07-13 10:36:33 -07:00
committed by GitHub
parent f6022da43c
commit 87ae0cca7e
4 changed files with 74 additions and 0 deletions
+27
View File
@@ -192,6 +192,33 @@ class CoinStore:
coins.add(CoinRecord(coin, row[1], row[2], row[3], row[4], row[8]))
return list(coins)
async def get_coin_records_by_parent_ids(
self,
include_spent_coins: bool,
parent_ids: List[bytes32],
start_height: uint32 = uint32(0),
end_height: uint32 = uint32((2 ** 32) - 1),
) -> List[CoinRecord]:
if len(parent_ids) == 0:
return []
coins = set()
parent_ids_db = tuple([pid.hex() for pid in parent_ids])
cursor = await self.coin_record_db.execute(
f'SELECT * from coin_record WHERE coin_parent in ({"?," * (len(parent_ids_db) - 1)}?) '
f"AND confirmed_index>=? AND confirmed_index<? "
f"{'' if include_spent_coins else 'AND spent=0'}",
parent_ids_db + (start_height, end_height),
)
rows = await cursor.fetchall()
await cursor.close()
for row in rows:
coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7]))
coins.add(CoinRecord(coin, row[1], row[2], row[3], row[4], row[8]))
return list(coins)
async def rollback_to_block(self, block_index: int):
"""
Note that block_index can be negative, in which case everything is rolled back
+23
View File
@@ -43,6 +43,7 @@ class FullNodeRpcApi:
"/get_coin_records_by_puzzle_hash": self.get_coin_records_by_puzzle_hash,
"/get_coin_records_by_puzzle_hashes": self.get_coin_records_by_puzzle_hashes,
"/get_coin_record_by_name": self.get_coin_record_by_name,
"/get_coin_records_by_parent_ids": self.get_coin_records_by_parent_ids,
"/push_tx": self.push_tx,
"/get_puzzle_and_solution": self.get_puzzle_and_solution,
# Mempool
@@ -463,6 +464,28 @@ class FullNodeRpcApi:
return {"coin_record": coin_record}
async def get_coin_records_by_parent_ids(self, request: Dict) -> Optional[Dict]:
"""
Retrieves the coins for given parent coin IDs, by default returns unspent coins.
"""
if "parent_ids" not in request:
raise ValueError("Parent IDs not in request")
kwargs: Dict[str, Any] = {
"include_spent_coins": False,
"parent_ids": [hexstr_to_bytes(ph) for ph in request["parent_ids"]],
}
if "start_height" in request:
kwargs["start_height"] = uint32(request["start_height"])
if "end_height" in request:
kwargs["end_height"] = uint32(request["end_height"])
if "include_spent_coins" in request:
kwargs["include_spent_coins"] = request["include_spent_coins"]
coin_records = await self.service.blockchain.coin_store.get_coin_records_by_parent_ids(**kwargs)
return {"coin_records": coin_records}
async def push_tx(self, request: Dict) -> Optional[Dict]:
if "spend_bundle" not in request:
raise ValueError("Spend bundle not in request")
+18
View File
@@ -117,6 +117,24 @@ class FullNodeRpcClient(RpcClient):
for coin in (await self.fetch("get_coin_records_by_puzzle_hashes", d))["coin_records"]
]
async def get_coin_records_by_parent_ids(
self,
parent_ids: List[bytes32],
include_spent_coins: bool = True,
start_height: Optional[int] = None,
end_height: Optional[int] = None,
) -> List:
parent_ids_hex = [pid.hex() for pid in parent_ids]
d = {"parent_ids": parent_ids_hex, "include_spent_coins": include_spent_coins}
if start_height is not None:
d["start_height"] = start_height
if end_height is not None:
d["end_height"] = end_height
return [
CoinRecord.from_json_dict(coin)
for coin in (await self.fetch("get_coin_records_by_parent_ids", d))["coin_records"]
]
async def get_additions_and_removals(self, header_hash: bytes32) -> Tuple[List[CoinRecord], List[CoinRecord]]:
try:
response = await self.fetch("get_additions_and_removals", {"header_hash": header_hash.hex()})
+6
View File
@@ -113,6 +113,12 @@ class TestRpc:
print(coins)
assert len(coins) >= 1
pid = list(blocks[-1].get_included_reward_coins())[0].parent_coin_info
pid_2 = list(blocks[-1].get_included_reward_coins())[1].parent_coin_info
coins = await client.get_coin_records_by_parent_ids([pid, pid_2])
print(coins)
assert len(coins) == 2
additions, removals = await client.get_additions_and_removals(blocks[-1].header_hash)
assert len(additions) >= 2 and len(removals) == 0