Skip to content
This repository has been archived by the owner on Dec 15, 2023. It is now read-only.

Commit

Permalink
Get transaction trace (#58)
Browse files Browse the repository at this point in the history
* Add shared testing resources

* Resolve pylint duplicate code issue
  • Loading branch information
badurinantun authored Mar 23, 2022
1 parent 7d46ae7 commit f17e2a8
Show file tree
Hide file tree
Showing 17 changed files with 249 additions and 28 deletions.
3 changes: 3 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ jobs:
- run:
name: Test get state update endpoint
command: poetry run pytest -s -vv test/test_state_update.py
- run:
name: Test get transaction trace endpoint
command: poetry run pytest -s -vv test/test_transaction_trace.py
- run:
name: Test plugin - dockerized
command: ./test/test_plugin.sh
Expand Down
4 changes: 4 additions & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@ max-line-length=150

[BASIC]
min-public-methods=1

[SIMILARITIES]
min-similarity-lines=20
ignore-imports=no
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,14 @@ If you don't specify the `HOST` part, the server will indeed be available on all
- `deploy`
- `get_block`
- `get_code`
- `get_full_contract`
- `get_state_update`
- `get_storage_at`
- `get_transaction_receipt`
- `get_transaction_trace`
- `get_transaction`
- `invoke`
- `tx_status`
- `get_transaction_receipt`
- `get_full_contract`
- `get_state_update`
- The following Starknet CLI commands are **not** supported:
- `get_contract_addresses`
- `estimate_fee` (currently always returning 0)
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ markers = [
"deploy",
"invoke",
"state_update",
"transaction_trace",
"web3_deploy",
"web3_messaging"
]
12 changes: 12 additions & 0 deletions starknet_devnet/origin.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ def get_transaction_receipt(self, transaction_hash: str):
"""Returns the transaction receipt object."""
raise NotImplementedError

def get_transaction_trace(self, transaction_hash: str):
"""Returns the transaction trace object."""
raise NotImplementedError

def get_block_by_hash(self, block_hash: str):
"""Returns the block identified with either its hash."""
raise NotImplementedError
Expand Down Expand Up @@ -75,6 +79,11 @@ def get_transaction_receipt(self, transaction_hash: str):
"events": []
}

def get_transaction_trace(self, transaction_hash: str):
tx_hash_int = int(transaction_hash, 16)
message=f"Transaction corresponding to hash {tx_hash_int} is not found."
raise StarknetDevnetException(message=message)

def get_block_by_hash(self, block_hash: str):
message=f"Block hash not found; got: {block_hash}."
raise StarknetDevnetException(message=message)
Expand Down Expand Up @@ -126,6 +135,9 @@ def get_transaction_status(self, transaction_hash: str):
def get_transaction(self, transaction_hash: str):
raise NotImplementedError

def get_transaction_trace(self, transaction_hash: str):
raise NotImplementedError

def get_block_by_hash(self, block_hash: str):
raise NotImplementedError

Expand Down
16 changes: 16 additions & 0 deletions starknet_devnet/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ async def get_block():
result_dict = starknet_wrapper.get_block_by_number(block_number)
except StarkException as err:
abort(Response(err.message, 500))

return jsonify(result_dict)

@app.route("/feeder_gateway/get_code", methods=["GET"])
Expand Down Expand Up @@ -194,6 +195,21 @@ def get_transaction_receipt():
ret = starknet_wrapper.get_transaction_receipt(transaction_hash)
return jsonify(ret)

@app.route("/feeder_gateway/get_transaction_trace", methods=["GET"])
def get_transaction_trace():
"""
Returns the trace of the transaction identified by the transactionHash argument in the GET request.
"""

transaction_hash = request.args.get("transactionHash")

try:
transaction_trace = starknet_wrapper.get_transaction_trace(transaction_hash)
except StarkException as err:
abort(Response(err, 500))

return jsonify(transaction_trace)

@app.route("/feeder_gateway/get_state_update", methods=["GET"])
def get_state_update():
"""
Expand Down
17 changes: 17 additions & 0 deletions starknet_devnet/starknet_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,23 @@ def get_transaction_receipt(self, transaction_hash: str):

return self.__origin.get_transaction_receipt(transaction_hash)

def get_transaction_trace(self, transaction_hash:str):
"""Returns the transaction trace of the tranasction indetified by `transaction_hash`"""

tx_hash_int = int(transaction_hash, 16)
if tx_hash_int in self.__transaction_wrappers:
status = self.__transaction_wrappers[tx_hash_int].transaction["status"]
transaction_wrapper = self.__transaction_wrappers[tx_hash_int]

if not hasattr(transaction_wrapper, "trace"):
raise StarknetDevnetException(
f"Transaction corresponding to hash {tx_hash_int} has no trace; status: {status}."
)

return transaction_wrapper.trace

return self.__origin.get_transaction_trace(transaction_hash)

def get_number_of_blocks(self) -> int:
"""Returns the number of blocks stored so far."""
return len(self.__num2block) + self.__origin.get_number_of_blocks()
Expand Down
6 changes: 6 additions & 0 deletions starknet_devnet/transaction_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ def __init__(
"transaction_index": 0 # always the first (and only) tx in the block
}

if status is not TxStatus.REJECTED:
self.trace = {
"function_invocation": execution_info.call_info.dump(),
"signature": tx_details.to_dict().get("signature", [])
}

def set_block_data(self, block_hash: str, block_number: int):
"""Sets `block_hash` and `block_number` to the wrapped transaction and receipt."""
self.transaction["block_hash"] = self.receipt["block_hash"] = block_hash
Expand Down
24 changes: 24 additions & 0 deletions test/expected/deploy_function_invocation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"calldata": ["0x0"],
"caller_address": "0x0",
"code_address": "0x3ffc1d4aca9668dfd9b5b6d374367b9dc52daed0ae23c54cb93ea2ea6e2dc72",
"contract_address": "0x3ffc1d4aca9668dfd9b5b6d374367b9dc52daed0ae23c54cb93ea2ea6e2dc72",
"entry_point_type": "CONSTRUCTOR",
"events": [],
"execution_resources": {
"builtin_instance_counter": {
"bitwise_builtin": 0,
"ec_op_builtin": 0,
"ecdsa_builtin": 0,
"output_builtin": 0,
"pedersen_builtin": 0,
"range_check_builtin": 0
},
"n_memory_holes": 0,
"n_steps": 40
},
"internal_calls": [],
"messages": [],
"result": [],
"selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194"
}
24 changes: 24 additions & 0 deletions test/expected/invoke_function_invocation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"calldata": ["0xa", "0x14"],
"caller_address": "0x0",
"code_address": "0x3ffc1d4aca9668dfd9b5b6d374367b9dc52daed0ae23c54cb93ea2ea6e2dc72",
"contract_address": "0x3ffc1d4aca9668dfd9b5b6d374367b9dc52daed0ae23c54cb93ea2ea6e2dc72",
"entry_point_type": "EXTERNAL",
"events": [],
"execution_resources": {
"builtin_instance_counter": {
"bitwise_builtin": 0,
"ec_op_builtin": 0,
"ecdsa_builtin": 0,
"output_builtin": 0,
"pedersen_builtin": 0,
"range_check_builtin": 0
},
"n_memory_holes": 0,
"n_steps": 67
},
"internal_calls": [],
"messages": [],
"result": [],
"selector": "0x362398bec32bc0ebb411203221a35a0301193a96f317ebe5e40be9f60d15320"
}
20 changes: 20 additions & 0 deletions test/shared.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""Shared values between tests"""

ARTIFACTS_PATH = "starknet-hardhat-example/starknet-artifacts/contracts"
CONTRACT_PATH = f"{ARTIFACTS_PATH}/contract.cairo/contract.json"
ABI_PATH = f"{ARTIFACTS_PATH}/contract.cairo/contract_abi.json"
EVENTS_CONTRACT_PATH = f"{ARTIFACTS_PATH}/events.cairo/events.json"
EVENTS_ABI_PATH = f"{ARTIFACTS_PATH}/events.cairo/events_abi.json"
FAILING_CONTRACT_PATH = f"{ARTIFACTS_PATH}/always_fail.cairo/always_fail.json"

BALANCE_KEY = "916907772491729262376534102982219947830828984996257231353398618781993312401"

SIGNATURE = [
"1225578735933442828068102633747590437426782890965066746429241472187377583468",
"3568809569741913715045370357918125425757114920266578211811626257903121825123"
]

EXPECTED_SALTY_DEPLOY_ADDRESS = "0x07c3a0c91048930f0258601db4211a3aa0578d9e746f15526a74eaabd38c56a4"
EXPECTED_SALTY_DEPLOY_HASH = "0x11ea05c61d78383e95cf44b70cfe15e74a55c7ceb1186c0c2ed743219f1f2ca"

NONEXISTENT_TX_HASH = "0x1"
22 changes: 11 additions & 11 deletions test/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,17 @@
call, deploy, invoke
)

ARTIFACTS_PATH = "starknet-hardhat-example/starknet-artifacts/contracts"
CONTRACT_PATH = f"{ARTIFACTS_PATH}/contract.cairo/contract.json"
ABI_PATH = f"{ARTIFACTS_PATH}/contract.cairo/contract_abi.json"
EVENTS_CONTRACT_PATH = f"{ARTIFACTS_PATH}/events.cairo/events.json"
EVENTS_ABI_PATH = f"{ARTIFACTS_PATH}/events.cairo/events_abi.json"
FAILING_CONTRACT_PATH = f"{ARTIFACTS_PATH}/always_fail.cairo/always_fail.json"

EXPECTED_SALTY_DEPLOY_ADDRESS = "0x07c3a0c91048930f0258601db4211a3aa0578d9e746f15526a74eaabd38c56a4"
EXPECTED_SALTY_DEPLOY_HASH = "0x11ea05c61d78383e95cf44b70cfe15e74a55c7ceb1186c0c2ed743219f1f2ca"
NONEXISTENT_TX_HASH = "0x1"
from .shared import (
ABI_PATH,
BALANCE_KEY,
CONTRACT_PATH,
EVENTS_ABI_PATH,
EVENTS_CONTRACT_PATH,
EXPECTED_SALTY_DEPLOY_ADDRESS,
EXPECTED_SALTY_DEPLOY_HASH,
FAILING_CONTRACT_PATH,
NONEXISTENT_TX_HASH
)

run_devnet_in_background(sleep_seconds=1)
deploy_info = deploy(CONTRACT_PATH, ["0"])
Expand All @@ -33,7 +34,6 @@
assert_transaction_not_received(NONEXISTENT_TX_HASH)

# check storage after deployment
BALANCE_KEY = "916907772491729262376534102982219947830828984996257231353398618781993312401"
assert_storage(deploy_info["address"], BALANCE_KEY, "0x0")

# check block and receipt after deployment
Expand Down
7 changes: 2 additions & 5 deletions test/test_cli_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
call, deploy, invoke
)

ARTIFACTS_PATH = "starknet-hardhat-example/starknet-artifacts/contracts"
from .shared import ARTIFACTS_PATH, SIGNATURE

CONTRACT_PATH = f"{ARTIFACTS_PATH}/auth_contract.cairo/auth_contract.json"
ABI_PATH = f"{ARTIFACTS_PATH}/auth_contract.cairo/auth_contract_abi.json"

Expand All @@ -28,10 +29,6 @@
assert_block(0, deploy_info["tx_hash"])
assert_receipt(deploy_info["tx_hash"], "test/expected/deploy_receipt_auth.json")

SIGNATURE = [
"1225578735933442828068102633747590437426782890965066746429241472187377583468",
"3568809569741913715045370357918125425757114920266578211811626257903121825123"
]
# increase and assert balance
invoke_tx_hash = invoke(
function="increase_balance",
Expand Down
4 changes: 1 addition & 3 deletions test/test_dump.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@

from .util import call, deploy, invoke, run_devnet_in_background
from .settings import GATEWAY_URL
from .shared import CONTRACT_PATH, ABI_PATH

ARTIFACTS_PATH = "starknet-hardhat-example/starknet-artifacts/contracts"
CONTRACT_PATH = f"{ARTIFACTS_PATH}/contract.cairo/contract.json"
ABI_PATH = f"{ARTIFACTS_PATH}/contract.cairo/contract_abi.json"
DUMP_PATH = "dump.pkl"

@pytest.fixture(autouse=True)
Expand Down
3 changes: 2 additions & 1 deletion test/test_postman.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@

from web3 import Web3

ARTIFACTS_PATH = "starknet-hardhat-example/starknet-artifacts/contracts"
from .shared import ARTIFACTS_PATH

CONTRACT_PATH = f"{ARTIFACTS_PATH}/l1l2.cairo/l1l2.json"
ABI_PATH = f"{ARTIFACTS_PATH}/l1l2.cairo/l1l2_abi.json"

Expand Down
6 changes: 1 addition & 5 deletions test/test_state_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@

from .util import deploy, invoke, load_contract_definition, run_devnet_in_background, get_block
from .settings import FEEDER_GATEWAY_URL

ARTIFACTS_PATH = "starknet-hardhat-example/starknet-artifacts/contracts"
CONTRACT_PATH = f"{ARTIFACTS_PATH}/contract.cairo/contract.json"
ABI_PATH = f"{ARTIFACTS_PATH}/contract.cairo/contract_abi.json"
BALANCE_KEY = "916907772491729262376534102982219947830828984996257231353398618781993312401"
from .shared import CONTRACT_PATH, ABI_PATH, BALANCE_KEY

@pytest.fixture(autouse=True)
def run_before_and_after_test():
Expand Down
Loading

0 comments on commit f17e2a8

Please sign in to comment.