Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: missing transaction rejection reason #269

Conversation

ca11ab1e
Copy link
Contributor

@ca11ab1e ca11ab1e commented Jul 27, 2022

Please check if the PR fulfills these requirements

  • The formatter, linter, and tests all run without an error
  • Tests for the changes have been added (for bug fixes/features)
  • Docs have been added / updated (for bug fixes / features)

What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)

Fix a 0.4 regression about missing rejection reason from failed transactions.

I also reworked several custom exceptions, to homogenize with others, and to ease using exception attributes outside the project.

What is the current behavior? (You can also link to an open issue here)

No way to know what was the root cause of a failed transaction.

What is the new behavior (if this is a feature change)?

Now, the rejection reason is filled properly.

Does this PR introduce a breaking change? (What changes might users need to make in their application due to this PR?)

No. I changed internal stuff only.

Other information

It's a critical bug fix for Ape StarkNet, and SithSwap. Hopefully it will gain some attention to move forward quickly :)

Also reworked several custom exceptions.
@codecov
Copy link

codecov bot commented Jul 27, 2022

Codecov Report

Merging #269 (f047871) into development (f099684) will increase coverage by 0.06%.
The diff coverage is 100.00%.

@@               Coverage Diff               @@
##           development     #269      +/-   ##
===============================================
+ Coverage        95.96%   96.03%   +0.06%     
===============================================
  Files               41       41              
  Lines             1909     1915       +6     
===============================================
+ Hits              1832     1839       +7     
+ Misses              77       76       -1     
Impacted Files Coverage Δ
starknet_py/contract.py 100.00% <100.00%> (ø)
starknet_py/net/client.py 94.36% <100.00%> (+0.08%) ⬆️
starknet_py/net/client_errors.py 94.73% <100.00%> (+1.40%) ⬆️
starknet_py/net/client_models.py 99.32% <100.00%> (ø)
starknet_py/net/gateway_schemas/gateway_schemas.py 95.70% <100.00%> (ø)
starknet_py/transaction_exceptions.py 87.50% <100.00%> (+6.25%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f099684...f047871. Read the comment docs.

Copy link
Member

@cptartur cptartur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for finding the issue with rejection_reason in TransactionReceipt. 👍

This issue is however a little bit more complicated - we're trying to orient starknet.py around the RPC api since it will become a default way of interaction with starknet at some point. That's why simply changing the typing of the TransactionReceipt is not currently possible, see my comments where I outline a possible solution for this issue, let me know what you think.

I believe these changes could be done on our side if you're fine with us keeping the tests improvements added in this PR and modifying the rest.

Comment on lines 220 to +223
if response.code != StarkErrorCode.TRANSACTION_RECEIVED.name:
raise Exception("Failed to send transaction. Response: {response}.")
raise TransactionFailedError(
code=response.code, error_message="Transaction not received"
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When adding transactions through the RPC (which will become the default way sooner than later), there's no code returned at all, and we're planning on removing this if completely soon: the flow will then be to invoke a transaction and do a result.wait_for_acceptance().

@@ -153,7 +153,7 @@ class TransactionReceipt:
block_number: Optional[int] = None
version: int = 0
actual_fee: int = 0
rejection_reason: Optional[str] = None
rejection_reason: Optional[Dict[str, Any]] = None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cannot be changed that way since the RPC rejection_reason is a string not a dict. What could perhaps be done is to have a subclass like GatewayTransactionReceipt that adds a code field and keeping rejection reason as a string.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIR I encountered a validation error because it's effectively a dict.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a dict in the gateway response but just a string in rpc. That's why I'd like to have rejection_reason as a string in TransactionReceipt (base class) since it's present in both, and then also have a code in GatewayTransactionReceipt. From my quick tests it seems like this dict only contains these two keys.

Comment on lines +14 to +19
def __str__(self):
return (
f"Client failed{f' with code {self.code}' if self.code is not None else ''}"
f": {self.message}"
)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error message is passed to the base Exception in super().__init__(self.message) so it should be printing correctly without overriding __str__.

Copy link
Contributor Author

@ca11ab1e ca11ab1e Jul 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The interesting change I would like to keep here is the fact that .message only includes the message argument, and not a modified version appending "Client failed...". It would ease using the message attribute outside the project (else I would need to "parse" the message, and try to get back the original value, which is not really future-proof nor clean).

@@ -161,7 +161,8 @@ async def wait_for_tx(
if result.block_number is not None:
return result.block_number, status
elif status == TransactionStatus.REJECTED:
raise TransactionRejectedError(result.rejection_reason)
reason = result.rejection_reason or {}
raise TransactionRejectedError(**reason)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same with changes to the TransactionReceipt, we'd prefer to keep the TransactionRejectedError oriented to RPC which doesn't include code. We could add a subclass of this exception specifically for the gateway_client, that incudes the code along with the message, so it doesn't confuse the RPC users.

@@ -114,8 +114,12 @@ class TransactionReceiptSchema(Schema):
block_number = fields.Integer(data_key="block_number", load_default=None)
version = fields.Integer(data_key="version", allow_none=True)
actual_fee = Felt(data_key="actual_key", allow_none=True)
rejection_reason = fields.String(
data_key="transaction_rejection_reason", allow_none=True, load_default=None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just acknowledging that the data_key was incorrect in this case and since our tests didn't check error messages we didn't catch that it's not working correctly.

@ca11ab1e
Copy link
Contributor Author

ca11ab1e commented Jul 28, 2022

I believe these changes could be done on our side if you're fine with us keeping the tests improvements added in this PR and modifying the rest.

Of course, the sooner it's fixed the better.

Am I getting it right if I say you will work on a proper patch on your side? If so, no worries, just go ahead :)

@cptartur
Copy link
Member

I believe these changes could be done on our side if you're fine with us keeping the tests improvements added in this PR and modifying the rest.

Of course, the sooner it's fixed the better.

Am I getting it right if I say you will work on a proper patch on your side? If so, no worries, just go ahead :)

Yes, we'd like to work on proper patch on our side. We'll however try to include the tests you added in this PR since they're very useful, so please keep the PR open for the time being.

@war-in war-in mentioned this pull request Jul 28, 2022
3 tasks
@war-in
Copy link
Contributor

war-in commented Jul 29, 2022

Closing this, because #271 was merged. Thanks for contributing!

@war-in war-in closed this Jul 29, 2022
@ca11ab1e ca11ab1e deleted the fix-tx-missing-rejection-reason branch July 29, 2022 12:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants