standardize blocks api (#306)

* adjusted block API return format
* blackified and updated version and changelog
* added to error message if no block with id was found

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>
This commit is contained in:
Lorenz Herzberger 2023-01-31 09:59:34 +01:00 committed by GitHub
parent 9a74a9c987
commit 3f65a13c46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 61 additions and 41 deletions

View File

@ -25,6 +25,9 @@ For reference, the possible headings are:
* **Known Issues**
* **Notes**
## [2.2.0] - 2023-31-01
* **Changed** standardized blocks API
## [2.1.0] - 2023-26-01
* **Added** validation for compose and decompose transaction types

View File

@ -20,4 +20,4 @@ class Block:
return Block(block_tuple[0], block_tuple[1], block_tuple[2], block_tuple[3])
def to_dict(self) -> dict:
return {"app_hash": self.app_hash, "height": self.height, "transactions": self.transactions}
return {"app_hash": self.app_hash, "height": self.height, "transaction_ids": self.transactions}

View File

@ -311,9 +311,12 @@ def get_block(connection, block_id=None) -> Union[dict, None]:
@register_query(TarantoolDBConnection)
def get_block_with_transaction(connection, txid: str) -> list[Block]:
def get_block_with_transaction(connection, txid: str) -> Union[dict, None]:
_block = connection.run(connection.space(TARANT_TABLE_BLOCKS).select(txid, index="block_by_transaction_id"))
return _block if len(_block) > 0 else []
if len(_block) == 0:
return
_block = Block.from_tuple(_block[0])
return _block.to_dict()
@register_query(TarantoolDBConnection)

View File

@ -311,12 +311,12 @@ class Planetmint(object):
return backend.query.store_block(self.connection, block)
def get_latest_block(self):
def get_latest_block(self) -> dict:
"""Get the block with largest height."""
return backend.query.get_latest_block(self.connection)
def get_block(self, block_id):
def get_block(self, block_id) -> dict:
"""Get the block with the specified `block_id`.
Returns the block corresponding to `block_id` or None if no match is
@ -333,13 +333,7 @@ class Planetmint(object):
if not block and block_id > latest_block_height:
return
result = {"height": block_id, "transactions": []}
if block:
transactions = backend.query.get_transactions(self.connection, block["transactions"])
result["transactions"] = [Transaction.from_dict(t.to_dict()).to_dict() for t in transactions]
return result
return block
def get_block_containing_tx(self, txid):
"""Retrieve the list of blocks (block ids) containing a
@ -351,11 +345,9 @@ class Planetmint(object):
Returns:
Block id list (list(int))
"""
blocks = list(backend.query.get_block_with_transaction(self.connection, txid))
if len(blocks) > 1:
logger.critical("Transaction id %s exists in multiple blocks", txid)
block = backend.query.get_block_with_transaction(self.connection, txid)
return blocks
return block
def validate_transaction(self, transaction, current_transactions=[]):
"""Validate a transaction against the current status of the database."""

View File

@ -3,8 +3,8 @@
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# Code is Apache-2.0 and docs are CC-BY-4.0
__version__ = "2.1.0"
__short_version__ = "2.1"
__version__ = "2.2.0"
__short_version__ = "2.2"
# Supported Tendermint versions
__tm_supported_versions__ = ["0.34.15"]

View File

@ -71,6 +71,9 @@ class BlockListApi(Resource):
pool = current_app.config["bigchain_pool"]
with pool() as planet:
blocks = planet.get_block_containing_tx(tx_id)
block = planet.get_block_containing_tx(tx_id)
return blocks
if not block:
return make_error(404, "Block containing transaction with id: {} not found.".format(tx_id))
return block

View File

@ -57,7 +57,7 @@ def test_init_chain_successfully_registers_chain(b):
assert query.get_latest_block(b.connection) == {
"height": 0,
"app_hash": "",
"transactions": [],
"transaction_ids": [],
}
@ -87,7 +87,7 @@ def test_init_chain_ignores_invalid_init_chain_requests(b):
assert query.get_latest_block(b.connection) == {
"height": 0,
"app_hash": "",
"transactions": [],
"transaction_ids": [],
}
@ -134,7 +134,7 @@ def test_init_chain_recognizes_new_chain_after_migration(b):
assert query.get_latest_block(b.connection) == {
"height": 2,
"app_hash": "",
"transactions": [],
"transaction_ids": [],
}
# requests with old chain ID and other requests are ignored
@ -156,7 +156,7 @@ def test_init_chain_recognizes_new_chain_after_migration(b):
assert query.get_latest_block(b.connection) == {
"height": 2,
"app_hash": "",
"transactions": [],
"transaction_ids": [],
}

View File

@ -86,13 +86,6 @@ def test_get_latest_block(b):
assert block["height"] == 9
@pytest.mark.bdb
@patch("planetmint.backend.query.get_block", return_value=None)
@patch("planetmint.Planetmint.get_latest_block", return_value={"height": 10})
def test_get_empty_block(_0, _1, b):
assert b.get_block(5) == {"height": 5, "transactions": []}
def test_validation_error(b):
from transactions.common.crypto import generate_key_pair

View File

@ -33,7 +33,7 @@ def test_get_block_endpoint(b, client, alice):
b.store_block(block._asdict())
res = client.get(BLOCKS_ENDPOINT + str(block.height))
expected_response = {"height": block.height, "transactions": [tx_dict]}
expected_response = {"app_hash": "random_utxo", "height": block.height, "transaction_ids": [tx.id]}
assert res.json == expected_response
assert res.status_code == 200
@ -60,16 +60,14 @@ def test_get_block_containing_transaction(b, client, alice):
b.store_block(block._asdict())
res = client.get("{}?transaction_id={}".format(BLOCKS_ENDPOINT, tx.id))
expected_height = block.height
assert res.json[0][2] == expected_height
assert res.json["height"] == expected_height
assert res.status_code == 200
@pytest.mark.bdb
def test_get_blocks_by_txid_endpoint_returns_empty_list_not_found(client):
res = client.get(BLOCKS_ENDPOINT + "?transaction_id=")
assert res.status_code == 200
assert len(res.json) == 0
assert res.status_code == 404
res = client.get(BLOCKS_ENDPOINT + "?transaction_id=123")
assert res.status_code == 200
assert len(res.json) == 0
assert res.status_code == 404

View File

@ -27,12 +27,10 @@ def test_get_block_returns_404_if_not_found(client):
@pytest.mark.bdb
def test_get_blocks_by_txid_endpoint_returns_empty_list_not_found(client):
res = client.get(BLOCKS_ENDPOINT + "?transaction_id=")
assert res.status_code == 200
assert len(res.json) == 0
assert res.status_code == 404
res = client.get(BLOCKS_ENDPOINT + "?transaction_id=123")
assert res.status_code == 200
assert len(res.json) == 0
assert res.status_code == 404
@pytest.mark.bdb
@ -55,3 +53,33 @@ def test_get_blocks_by_txid_endpoint_returns_400_bad_query_params(client):
res = client.get(BLOCKS_ENDPOINT + "?transaction_id=123&status=123")
assert res.status_code == 400
assert res.json == {"message": "Unknown arguments: status"}
@pytest.mark.bdb
@pytest.mark.usefixtures("inputs")
def test_get_latest_block(client):
res = client.get(BLOCKS_ENDPOINT + "latest")
assert res.status_code == 200
assert len(res.json["transaction_ids"]) == 10
assert res.json["app_hash"] == "hash3"
assert res.json["height"] == 3
@pytest.mark.bdb
@pytest.mark.usefixtures("inputs")
def test_get_block_by_height(client):
res = client.get(BLOCKS_ENDPOINT + "3")
assert res.status_code == 200
assert len(res.json["transaction_ids"]) == 10
assert res.json["app_hash"] == "hash3"
assert res.json["height"] == 3
@pytest.mark.bdb
@pytest.mark.usefixtures("inputs")
def test_get_block_by_transaction_id(client):
block_res = client.get(BLOCKS_ENDPOINT + "3")
print(block_res.json)
tx_id = block_res.json["transaction_ids"][0]
res = client.get(BLOCKS_ENDPOINT + "?transaction_id=" + tx_id)
assert res.json["height"] == 3