-
Notifications
You must be signed in to change notification settings - Fork 166
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
Add FLIP for removing public resource fields #739
Conversation
This pull request is being automatically deployed with Vercel (learn more). 🔍 Inspect: https://vercel.com/onflow/flow-docs/HEqcyMZb2Lt8Fvm1329Sazrcadja [Deployment for 61f5385 failed] |
What will happen to existing code that already have public fields in them. Also you say |
This is a great question, and probably the largest technical challenge in implementing something like this: we would need to have a migration path to allow people to rewrite existing code with public resource fields.
Yes, structs would not be changed as part of this proposal. |
I am against this as you know. Problem for me is 2 sided, first one is when we remove public fields, we are giving away too much creative choice to the developer. It means there can be a lot of different implementations which can be correct in their own way. And this will lead to very wide range of implementations. I think it is always nice to have a single straight forward way to implement something. From developer perspective (with example on the FLIP) : We have few options for backing storage for variable:
If we think all of them, first We also have multiple options for query:
Let's say I implemented:
So I made this future proof as I can add more fields ( which I cannot add to resources currently. spoiler alert: future footgun here) or worse:
Oh actually now I can even change/destroy the NFT user has, all I need to do is make a mapping function from id -> real_id. same for PS: I think this direction is taking away We already ended up with NFTs with only |
With #703 and a potential follow-up proposal for nested composite values, which improves the safety aspect for resources and their nested data, I do not see a strong reason to prevent the declaration of public fields in resources. |
Agreed! I like the declarative aspect of fields that can be read. Both their declaration and access is straight-forward, where as this proposal could lead to developers having to come up with functions that properly allow read access to the nested data, potentially getting it wrong.
We would of course still allow private variables, and the current limitation for code updates to not allow adding fields should not play a role here. I think I follow what you are trying to point out with the remaining part of your message: Given that the removal of public fields will require an alternative, this is is going to be "accessor functions", which, instead of fields, have the potential to be updated. This would lead developers to prefer not actually storing data in resources but in a central ledger, and ultimately might be even abused for "rug pulls". This is a really great argument and I agree with it fully! This seems to be a very strong argument against |
The way I see it, there are two primary reasons to consider removing public fields, both of which are touched on above, but allow me to reiterate them for clarity.
-- The arguments against removing public fields are also two-fold, it seems:
-- If we require that all Resource data members are private, we force smart contract developers to do the following:
Don't those sound like things we want everyone writing smart contracts to think about? 😉 |
I think we can agree that discussion here is not on technical level, more it is decision on philosophy of the Flow. I mentioned this before in Discord that there is a lack of basic ruleset ( I mentioned that as half jokingly "Flow Constitution" ) of ideals. Let's get out of technical restrictions etc for a moment. What is Cadence? Let's read from docs.
Ok so far, we can summarize it as : Cadence -> Smart Contract Language It is not for me Smart EULA Language. As we have upgradeable contracts, it is very tricky to balance power between
I think those goals are amazing, even though a lot of cadence developers lack ability to "design by contract", resources are granting some freedom to Users.
This is in my opinion a bit "Focus on developer productivity and usability" vs "Safety and security".
Let's think in a way that: Contract owner can do hostile action, no point to protect against that. ( Though I don't agree ) Now we lost one of the selling points of Cadence: Composability. How can you use composability when you are in untrusted environment? I am all in for freedom, but by definition, contracts and interfaces are to define restrictions. Maybe it is better to not be able to implement everything in Flow ( also in Cadence ), but implement things we can in the best way. For me not being able to implement
I agree those are great things to have. But I just don't agree the way it should be with black box resources. Removing Not the best example but, when I see some resource: ```A.0b2a3299cc857e29.TopShot.NFT(uuid: 32849189, id: 10442766, data: A.0b2a3299cc857e29.TopShot.MomentData(setID: 26, playID: 1066, serialNumber: 14866))```` I know it is minted by: '0b2a3299cc857e29' which is official TopShot Account. With id: 10442766, and versus:
First one is set to stone: I own serial 14866 of the moment. You can if you want later mint 1000000 of this moment, I still own the 14866. ( This reminds me on book market, market can even value new 1 million prints as worthless while giving much value on the first edition print (first 15000 moments for example ) )
|
To me, it comes down to the following: Can someone trust an FT or NFT asset without knowing that it has been reviewed by a capable Cadence developer (possibly oneself)? To me the answer is, every single time, "No. Unequivocally, no." Should it be the case that a "good" NFT contract uses a constant variable for the ID? Yes! Absolutely. I agree that's what should be done, and I think anyone reviewing an NFT implementation should be very skeptical if they see that's not the case! But even if we enforce that at the language level, and with the definition of the NFT spec, that doesn't mean you can trust every NFT implementation. I don't believe we should lock down the metadata representation for NFTs, for example, because I think there are some really useful and interesting ways to have dynamic metadata on NFTs. But that means that buyers of NFTs need to know the creator isn't going to use that capability to cause harm. And if the smart contract author can change all of the other data associated with the NFT, I'm not sure how valuable it is to make sure they can't mess with the ID. The reason I used the Ampleforth example isn't because I think that Ampleforth is a critical piece of infrastructure that Flow needs to have, but because it shows the dangers trying to presuppose all the "right ways" to think about a problem. They changed the way that people thought about how I consider the bar for "blocking behaviour" very high. And I don't think making the Here's an interesting thought experiment. Let's say we changed the FT and NFT interfaces to use methods for |
@dsainati1 What's the status of this PR? Should it be archived or is this still in play? |
I don't think we have reached consensus here, so I don't feel comfortable archiving it. |
Over the next bit we will be working on moving FLIPs to their own repo. We can merge this as draft and continue discussion in the forums if you'd like to keep it open past the end of next week. How does that sound? |
Yea that sounds good to me |
Thank you for your feedback on the rug-pull concern @dete, it seems like it is not as big a concern as we assumed.
The proposal lists a couple drawbacks:
Another drawback not yet mentioned (AFAICS) is that this adds a special rule to the language, which developers have to learn and might stumble upon ("huh? I can declare a public field in a struct or contract, but in a resource I cannot? Why?"). With #703 accepted, implemented, and soon to be released as part of the Secure Cadence release in the next spork, Maybe to reverse the question: What arguments are left to remove public fields? Are they worth the drawbacks? If standards and contracts opt to use public getter functions instead of exposing public fields, they can. |
Will this also effect synthetic fields in the future? Or simply if we implemented synthetic fields already, doesn't it make this FLIP unnecessary ? |
Co-authored-by: Robert E. Davidson III <[email protected]>
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Synthetic fields were proposed in the original language spec, but have so far not been implemented. They are somewhat related: I guess if we were to implement synthetic fields and this proposal gets accepted, then we should also require synthetic fields in resourced to be non-public. |
Yeah it would be little weird to having synthetic field and then accessing not public I guess. ( in the end it is getter/setter function combo ) Though if we allow public synthetic fields, then one step ahead is some decorator to auto convert private fields to public synthetic ones. (Virtually) |
@dsainati1 Could you please provide a summary of the current discussion, i.e. what the current sentiment is, and if and what any outstanding questions are? Thanks! |
This FLIP seems to have a majority opinion against implementing it, but there are compelling arguments on both sides. @bluesign and @turbolent have outlined concerns about how removing public resource fields will result in too many differing ways to implement the same kind of resource logic, making using them more difficult and potentially adding a safety footgun wherein bad actors can implement malicious accessor functions, or change the behavior of previously working accessors. @dete has pointed out, however, that the by constraining developers into using uniform implementations for their resources, design paradigms that make heavy use of public fields also necessarily decrease the power that a good actor has when writing resource implementations. Specifically he cites the example wherein Flow's FT contract requires its balance to be a public field, which prevents implementors from having something like an exchange rate in their token that automatically adjusts its value according to an external factor. He also cites mutability concerns, wherein public fields, especially those that contain user-defined types (but also any field through a reference), can be mutated unexpectedly, and that removing public resource fields would defend against this footgun. This suggests to me that there are two primary points of discussion on this FLIP: 1) the design question of whether or not we want resources to be more like collections of public data without much implementation logic, or whether we want resources to be black boxes that implement any behavior they choose, and 2) whether having public fields on resources is a security concern because they are unexpectedly mutable. It seems as though the prevailing (but not universal) sentiment regarding (1) is that developers would prefer resources to be more transparent in terms of what data can be read. On (2) however, there is less consensus. An open question then, perhaps for @dete to answer: if the remaining portion of external mutability unaddressed by #703 were to be fixed (perhaps via something like #1056), would that assuage your security concerns about public resource fields? Would you then feel comfortable closing this FLIP? |
Maybe if we can somehow make this mutability / readonly reference things, what I would love to have: you can access everything to view of a resource ( including private ), but you cannot somehow copy fields ( probably shared as reference too ) or access mutable methods. This way as everything on blockchain is possible to see, we could have that part on chain too. Then we can remove pub(set) fields from resources, even can make resources black box. |
Closing after short chat with Dete |
This FLIP was closed as there has not been any discussion for several month, and so far there is no majority / consensus for accepting it. |
This adds a FLIP proposing to remove public fields on resources in Cadence. See more discussion here: onflow/cadence#1322
For contributor use:
master
branchFiles changed
in the Github PR explorer