-
Notifications
You must be signed in to change notification settings - Fork 76
Add nile-account
flag to set Nile artifacts path
#315
Conversation
Hi Andrew! This approach to declaring looks great!
I just want to mention that 309 is not completely solved by it. We still have the problem with status, which tries to "infer" the artifact of the contract instead of getting it from the deployments.txt file (using Lines 76 to 85 in 98ce378
Every time a transaction is sent through an account (most of the time) status is going to fail to try to get the Account artifact, which is already registered correctly in deployments.txt. Keeping in mind that status uses the contracts registered in this file, and this file contains the artifacts, I think it makes sense to use the artifacts already registered instead of trying to pass EDIT: Why are we registering the artifact in deployments.txt, if we are going to assume they are always inside the nile artifact folder, and if not, we are going to require |
Agree on reading the deployments file. This file exists for these reasons, it also makes custom account integration easier down the road.
We should use the artifact, but a possible reason to register it if not would be to maintain the file structure/invariants. |
Thank you for the early review, @ericnordelo! I have some responses:
This is partially correct^. The issue is actually with
Being that we only have the artifacts for
This is not entirely accurate. While it won't be able to iterate over the precompiled contracts, I wouldn't say that the status is going to fail. There's already handling for contracts not found https://github.com/OpenZeppelin/nile/blob/main/src/nile/utils/debug.py#L30-L37
which looks like this:
I will include a solution for better error handling in cases where the user tries to declare a contract through an undeclared/undeployed sender account. What is not handled, however, is the unregistration of the account through this process (the declaration is nevertheless removed successfully). I'm still looking into the reason. IMO this whole process highlights why we should prioritize separating account initialization and deployment (#278). With this separation, I believe we'll have stronger control over the account flow and error handling thus better UX. Forgive me, that's a lot 😅 I'd love some feedback! |
Thanks for the context @andrew-fleming!
Yes! My bad. The issue is with debug, not with status, I didn't explain myself well. I said status because debug is a type of status, and is the default that runs (issue only happens if the underlying transaction reverts).
Not sure what we are doing different, but following the same steps provided by Eric in the issue, the traceback of the error I received is this one:
Here you can see that the
The status is failing already for declare in the issue right? what is the difference with other commands going through accounts? I think is important to discover why your traceback and mine are different in the first place for me to understand this point. |
i get the same as Eric. so in short, if i understood correctly:
i assume Andrew's getting a different error either because he added/compiled a new artifact, or because he has a local fix already |
Haha no worries! This was a tricky issue, and I just wanted to be as precise as possible.
So the assumption is correct in that the error is raised by Also @martriay ^ |
But the error says the missing file is |
Excellent question. The Account.json is being set in |
@@ -26,6 +26,22 @@ def register(pubkey, address, index, alias, network): | |||
json.dump(accounts, file) | |||
|
|||
|
|||
def unregister(address, network): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you add tests for this?
src/nile/core/account.py
Outdated
): | ||
"""Declare a contract through an Account.""" | ||
max_fee, nonce, _ = await self._process_arguments(max_fee, nonce) | ||
|
||
if nile_account: | ||
assert overriding_path is None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why asserting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's a nile_account, an overriding_path wouldn't make sense because the path to the artifacts lies within the package. The assertion isn't absolutely necessary, but the user might get the wrong idea about where the account is coming from...an error message with the assertion would be helpful
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but wouldn't this let users deploy custom accounts?
await account.declare( | ||
contract_name, | ||
alias=alias, | ||
max_fee=max_fee, | ||
overriding_path=overriding_path, | ||
mainnet_token=token, | ||
watch_mode=watch_mode, | ||
nile_account=nile_account, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about making it a constructor argument and object attribute? i.e. self.is_nile_account
it could be leaner if we eventually need it for other operations, and it would debloat the function's arguments. although right now it's the same since it's just here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can maybe add this in the future, but I don't think this would work here. The point of nile_account
is to direct the path to the Nile artifacts. Really, it's just for declaring a Nile account, so we need a way to adjust the path for this specific type of declaration. In other words, when an account wants to declare a Nile account, use the flag to change the path. For other declarations, Nile assumes the local artifacts/
path.
IMO a better fix would be to iterate both paths checking for the target contract. That way, we don't have to worry about any of this. I already have a working example of this improvement, but for the sake of getting this shipped, I decided not to include it
src/nile/utils/debug.py
Outdated
return await execute_call(**execute_args) | ||
except FileNotFoundError: | ||
# Change path in contracts to locate Nile artifacts | ||
contracts = _get_contracts_data(contracts_file, network, addresses, True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is using one or the other, right? could it be that the traceback includes both nile and non-nile artifacts? if so, can't both paths be used simultaneously (and avoid re-executing the command)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that should work. I was initially worried about conflicting "Account"s (with how common the contract name is), but that shouldn't be an issue now with the nile_account
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could also have a different name for Nile's
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good @andrew-fleming ! Left a couple of comments. A refactor for the overriding_path
handling flow would be helpful I think, but that is out of the scope of this PR.
src/nile/core/account.py
Outdated
|
||
def set_nile_artifacts_path(): | ||
"""Set path to find Nile's precompiled artifacts.""" | ||
pt = os.path.dirname(os.path.realpath(__file__)).replace("/core", "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to not import pt
from nile.common
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we use it, I would rename pt
to nile_root_path
or something similar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to not import pt from nile.common?
Nope, good call!
Co-authored-by: Eric Nordelo <eric.nordelo39@gmail.com>
@@ -137,8 +139,7 @@ def get_class_hash(contract_name, overriding_path=None): | |||
|
|||
def get_account_class_hash(contract="Account"): | |||
"""Return the class_hash of an Account contract.""" | |||
pt = os.path.dirname(os.path.realpath(__file__)).replace("/core", "") | |||
overriding_path = (f"{pt}/artifacts", f"{pt}/artifacts/abis") | |||
overriding_path = (NILE_BUILD_DIR, NILE_ABIS_DIR) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😍
src/nile/core/account.py
Outdated
): | ||
"""Declare a contract through an Account.""" | ||
max_fee, nonce, _ = await self._process_arguments(max_fee, nonce) | ||
|
||
if nile_account: | ||
assert overriding_path is None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but wouldn't this let users deploy custom accounts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good! in the future we should add more tests for account file management, like register
tests/commands/test_account.py
Outdated
QUERY_VERSION, | ||
TRANSACTION_VERSION, | ||
UNIVERSAL_DEPLOYER_ADDRESS, | ||
) | ||
from nile.core.account import Account, set_nile_artifacts_path | ||
from nile.core.account import Account, get_nile_artifacts_path |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems like a common
function, or maybe even just a constant
tests/test_accounts.py
Outdated
@@ -0,0 +1,73 @@ | |||
"""Tests for accounts file.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
then i'd call it tests/test_accounts_file.py
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good to go! Left a small suggestion.
src/nile/core/account.py
Outdated
@@ -297,3 +303,8 @@ def get_counterfactual_address(salt=None, calldata=None, contract="Account"): | |||
constructor_calldata=calldata, | |||
deployer_address=0, | |||
) | |||
|
|||
|
|||
def get_nile_artifacts_path(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be a constant.
424bc90
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
This PR proposes to add the
nile-account
flag toaccount.declare
which will create an overriding_path to Nile's precompiled artifacts. This will remove the need to manually set the path for Account declarations.Nile account declarations will look like this:
as opposed to something like:
Resolves #309.
Update
In the event that an issue arises from the Account contract itself, the PR will now find the artifact in Nile's own artifacts directory. In most cases where errors occur from the contract(s) called from an account,
Debug
will return the underlined code where the error is coming from in the contracts. The errors referenced specifically in Account will not return the underlined Cairo code becauseDebug
needs the actual.cairo
contract to reference.This PR also proposes to:
deploy
,declare
, andsend
. Previously, these deployments would fail but the account would still be registered. This is because the CLI only passedwatch_mode
to the account method and not the account initialization/deployment.unregister
failed account deployments. Though, it may be useful to keep the account information, I think it's possible that confusion may arise from having the account information when its deployment failed. If it's preferred to leave the data, we can remove theunregister
quite easily.