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

Deploy origin for pallet-contracts #3196

Closed
Szegoo opened this issue Feb 3, 2024 · 17 comments · Fixed by #3377
Closed

Deploy origin for pallet-contracts #3196

Szegoo opened this issue Feb 3, 2024 · 17 comments · Fixed by #3377

Comments

@Szegoo
Copy link
Contributor

Szegoo commented Feb 3, 2024

In some cases, it could be useful to have permissioned contract deployment on a chain.

Probably the easiest way to enable this would be to add a new type to the config, e.g.:

type DeployOrigin: EnsureOrigin<Self::RuntimeOrigin>;
@Szegoo Szegoo changed the title Upload origin for pallet-contracts Deploy origin for pallet-contracts Feb 3, 2024
@bkchr
Copy link
Member

bkchr commented Feb 4, 2024

@Szegoo I assume you would work on this?

CC @athei

@Szegoo
Copy link
Contributor Author

Szegoo commented Feb 5, 2024

@Szegoo I assume you would work on this?

Yes, will open a PR soon. Just wanted to confirm this is sensible first.

@athei
Copy link
Member

athei commented Feb 6, 2024

Yes this makes sense to me.

@Szegoo
Copy link
Contributor Author

Szegoo commented Feb 12, 2024

Actually, this is not as straightforward as I thought. The contracts api assumes that the origin is an account, which might not be the case if we want to do something as I suggested in the issue description.

Maybe have something like this instead:

type DeployOrigin: Contains<T::AccountId>;

And then for example if we wanted to allow only members from a specific collective to deploy a contract we could have the following in the runtime config:

type DeployOrigin = TechnicalCommitteeMembershipInstance;

This is possible since the pallet_membership implements the Contains trait.

@bkchr @athei thoughts?

@bkchr
Copy link
Member

bkchr commented Feb 12, 2024

The contracts api assumes that the origin is an account, which might not be the case if we want to do something as I suggested in the issue description.

Can you explain what you mean?

I don't really see why we need to use Contains here and not EnsureOrigin.

@athei
Copy link
Member

athei commented Feb 12, 2024

Yes, a contract assumes that any other contract has an AccountId. But you can can construct a Origin::Signed from that AccountId and test it against your initially suggested

type DeployOrigin: EnsureOrigin<Self::RuntimeOrigin>;

@xlc
Copy link
Contributor

xlc commented Feb 12, 2024

You could add a signed extension to do whatever origin validation required. No need to modify the pallet.

@athei
Copy link
Member

athei commented Feb 12, 2024

That would only work if you care about contracts deployed by a signed account but not by other contracts. Meaning you can't stop contracts from instantiating other contracts with that approach.

@Szegoo
Copy link
Contributor Author

Szegoo commented Feb 13, 2024

I don't really see why we need to use Contains here and not EnsureOrigin.

For each contract we store CodeInfo, which contains an owner property of type AccountId. If we used EnsureOrigin the origin might not be associated with an AccountId. E.g. if we were to set the DeployOrigin to root what account would be the owner of the deployed code?

@athei
Copy link
Member

athei commented Feb 13, 2024

E.g. if we were to set the DeployOrigin to root what account would be the owner of the deployed code?

Contracts do not have owners. At least not as a concept of pallet-contracts. What you are referring to is probably which Origin does a contract constitute. As mentioned above it would be Origin::Signed(contract_account_id). You could match that to your EnsureOrigin filter. That test would rightfully fail of you set the DeployOrigin to only allow Origin::Root. But the filter could also for certain Origin::Signed to deploy with no problem. I really don't see the problem here.

You need to start getting more specific if you need further help.

@Szegoo
Copy link
Contributor Author

Szegoo commented Feb 13, 2024

As mentioned above it would be Origin::Signed(contract_account_id)

I get that. What I was referring to is this.

I am definitely not deep into the contracts pallet, but AFAIU the deployed code has an owner: link. What I was asking was who would be the owner of the uploaded code if the origin is not signed(e.g. root)?

@bkchr
Copy link
Member

bkchr commented Feb 13, 2024

E.g. if we were to set the DeployOrigin to root what account would be the owner of the deployed code?

Then you can use EnsureRootWithSuccess and pass some accountid that represents the root account. We already have done this somewhere, but I can right now not find it.

@athei
Copy link
Member

athei commented Feb 14, 2024

I am definitely not deep into the contracts pallet, but AFAIU the deployed code has an owner: link. What I was asking was who would be the owner of the uploaded code if the origin is not signed(e.g. root)?

Okay yes I get it now. I thought you were talking about instantiating a contract. But you mean uploading new code. Which of the two you want to make permissioned? Only the uploading of new code?

@Szegoo
Copy link
Contributor Author

Szegoo commented Feb 16, 2024

Then you can use EnsureRootWithSuccess and pass some accountid that represents the root account. We already have done this somewhere, but I can right now not find it.

Yeah, this seems exactly like what would be needed. Since the contracts pallet assumes in code deployment and instantiation that an account id associated with the origin, by making this slight adjustment to my initial suggestion we can make it work:

type DeployOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = Self::AccountId>;

Which of the two you want to make permissioned? Only the uploading of new code?

I think restricting both would make the most sense.

@athei
Copy link
Member

athei commented Feb 18, 2024

type DeployOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = Self::AccountId>;

Yes, but there is a shorthand for this as Basti mentioned: EnsureRootWithSuccess.

Which of the two you want to make permissioned? Only the uploading of new code?

I think restricting both would make the most sense.

I think two config knobs would make sense then. You might want to allow everyone to instantiate existing code but make the upload restricted.

@pgherveou
Copy link
Contributor

Seeing this a bit late,
but why can't we just leverage frame_system::BaseCallFilter here?

Zeigeist is doing something like this

https://github.com/zeitgeistpm/zeitgeist/blob/22992bc631ec321eec906be6dfe07b6bc3d2dfc5/runtime/zeitgeist/src/lib.rs?plain=1#L148-L157

@athei
Copy link
Member

athei commented Mar 5, 2024

When discussing the issue here I thought the goal would be to also prevent contract from instantiating. Without this requirement the call filter would suffice AFAIK.

github-merge-queue bot pushed a commit that referenced this issue Mar 6, 2024
Closes: #3196

---------

Co-authored-by: Alexander Theißen <alex.theissen@me.com>
Co-authored-by: PG Herveou <pgherveou@parity.io>
bgallois pushed a commit to duniter/duniter-polkadot-sdk that referenced this issue Mar 25, 2024
Closes: paritytech#3196

---------

Co-authored-by: Alexander Theißen <alex.theissen@me.com>
Co-authored-by: PG Herveou <pgherveou@parity.io>
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 a pull request may close this issue.

5 participants