Open agostbiro opened 1 year ago
I did a bit a of testing now with this contract:
#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize)]
pub struct Contract {
message: String,
}
#[near_bindgen]
impl Contract {
pub fn get_greeting(&self) -> String {
return self.private_get_greeting();
}
#[private] pub fn private_get_greeting(&self) -> String {
return self.message.clone();
}
}
And I found that I can call get_greeting
both with an Account::call
and a Contract::view
, so maybe it's fine as it is and we don't have to disallow private view methods?
And I found that I can call
get_greeting
both with anAccount::call
and aContract::view
, so maybe it's fine as it is and we don't have to disallow private view methods?
This is because you're not using the #[private]
annotation for what it's intended for. The use case is making a cross-contract call from the current contract (commonly used for callbacks). If you call private_get_greeting
as a view call (you have to call directly because you can't schedule the call in view context), you'll see it will fail with handler error: [Function call returned an error: wasm execution failed with error: HostError(ProhibitedInView { method_name: "predecessor_account_id" })]
.
For reference, the code I'm referring to:
pub fn get_greeting() -> Promise {
Self::ext(env::current_account_id()).private_get_greeting()
}
#[private] pub fn private_get_greeting(&self) -> String {
"test".to_string()
}
Where I don't think there is an issue, since these can both just be called in a transaction rather than a view call, but the semantics are a bit muddied because &self
is documented as meaning a view call. This just works because view calls can be called as transactions (as there is no view/transaction context passed from the runtime).
Thanks for clarifying @austinabell ! I managed to reproduce the error with my code when calling private_get_greeting
directly as view, and with the code that you provided by calling get_greeting
as view.
I'm still not 100% clear on why the error doesn't occur when calling get_greeting
as view in my code. Is the code executed different or is the runtime environment different? Is there anywhere I can read more about this?
Btw while testing this I ran some circles, because I didn't realize that the test:integration
command doesn't rebuild the contract, so I'm submitting a PR for that in create-near-app
(edit: it's https://github.com/near/create-near-app/pull/2014).
I'm still not 100% clear on why the error doesn't occur when calling get_greeting as view in my code. Is the code executed different or is the runtime environment different?
@agostbiro self.private_get_greeting()
just calls the function on the struct, but calling view function from RPC, it goes through an onramp created by near_bindgen
:
Is there anywhere I can read more about this?
I only trust the source code:
Ah got it, thanks @frol !
So the conclusion seems to me that there are no changes needed regarding private view functions. Did I understand that correctly?
@agostbiro Well, given that there is no use for private view functions (they will just fail), it would be great to forbid them at compilation time (#private
+ &self
should be forbidden). Would it be hard to implement? (sounds like a trivial assert after the refactoring, but I don't have the full context in my head at the moment)
@frol yeah it's a very small change. I tried it now and the following tests are failing after disallowing private view methods:
With this many tests failing I'm a little concerned about breaking a lot of code in the wild if we disallow private view methods, but if that's unfounded I'm happy to adjust the tests.
@frol the main issue here is that a lot of contracts in the wild have methods that are view according to their self
usage, but not view semantically and are always called in transaction context (@agostbiro provided some examples above). Making this change will break the existing code for them which is why this would have to be a multistep process where we have to decide whether we want to bother with enforcing the view/call unambiguity first.
The purpose of this issue is to follow up the conversation from #890 and #1025 on private view methods. I quote here the comments to make it easier to overview. Related issue: https://github.com/near/near-sdk-rs/issues/937.
In #890 @itegulov asked:
In #890 @austinabell replied:
In #1025 @agostbiro wrote:
In #1025 @itegulov replied: