Forum for discussion of mid, final term and final project

How to force to use `send` instead of `call` in web3?

How to force to use `send` instead of `call` in web3?

by ALESSANDRO PAGIARO -
Number of replies: 10
I was trying to build a front end. I've notice that, in web3, if I invoke a contract function using `Contract.func.send()`, then the callback returns the transaction hash. So, I've tried to use `Contract.func.call()` but, in this case, the local node returns the content without changing the accessRight (in fact the call discards all the changes and returns the value). The problem is, since all this things depends only on the local implementation, a potential client should modify its UI and retain all the accessRight for unlimited time, right? 


We have to manage this case or not?


Moreover, I've read on StackOverflow that, transaction not returns any data outside the EVM but the tx hash, so, they suggest to produce an event to retrieve the data. This approch destruct any logic that requires to pay the content. 

Anothe solution to get the date (the content itself in this case), is to invoke the `call()` then the `send()` to apply the changes to blockchain. In this case, the client will retrieve the data immediately AND then, have to pay Ether to broadcast that he has no more access right... Mmm... 

Any solution?

In reply to ALESSANDRO PAGIARO

Re: How to force to use `send` instead of `call` in web3?

by DAMIANO DI FRANCESCO MAESA -

It looks to me you are doing a bit of a mess. Try to study again the difference between pure and state modifying functions. I think a misunderstanding about it might be the cause of your doubts.

In reply to DAMIANO DI FRANCESCO MAESA

Re: How to force to use `send` instead of `call` in web3?

by ALESSANDRO PAGIARO -

There are a lot of questions online but the topic appears a bit confused. 

Here says that "Keep in mind though, that this will return the transaction hash, and not the [returned] value itself. If you want the [returned] value, you need to get the function through a call", where a call, if I understand, is a local invocation of the transaction but the changes are discarded and the result is returned.

On Ethereum forum says that "Transactions cannot return results to web3.js. Note this! The [sendCoin] function returns a value but this cannot be checked in your test. This method is a transaction (i.e., something that modifies values or send ether), and the result of a transaction to web3.js is a transaction hash", so I cannot recover the value returned by the function without having an event, that implies that a malicious user can watch on that event type and read all content.

On Etherem StackExchange forum, the solution proposed are 1) Mutate the state via a transaction and then read the resulting state by calling a view function that is useless for us since a function called later cannot read the data (the content is consumed) 2) Mutate the state via a transaction and emit an event that's observed by the caller (that is the same solution proposed on Ethereum Forum but is very unsecure).

In same place that I don't find now, I've read that Remix performs a call (without changing the data) and then performs a transaction. The problem is that, potentially, this two invocation can be independent so a malicious user can simply delete the trasanction invocation, then retrieving all the content unlimited times.

So, we have to perform a call and then invoke on it the transaction even if the result is ready to be shown and bypass any security issuu?  

In reply to ALESSANDRO PAGIARO

Re: How to force to use `send` instead of `call` in web3?

by DAMIANO DI FRANCESCO MAESA -

It all makes sense to me, have you studied the difference between transaction and "non state modifying call"? It seems to me that we also talked about it in person during question time. Transactions are not meant to return values, they are a decentralised state update mechanism, not function calls. Also the following phrase makes no sense in a public blockchain:

"so I cannot recover the value returned by the function without having an event, that implies that a malicious user can watch on that event type and read all content."

There is no such thing as "security issue".

In reply to DAMIANO DI FRANCESCO MAESA

Re: How to force to use `send` instead of `call` in web3?

by ALDO D'AQUINO -

Sorry for the intrusion, but I have the same problem.
I have studied the topic well and I have clear the difference between a function with view visibility modifier and one that changes the status.

My problem is as follows:

  • a user u has access rights to x and calls consumeContent
  • the consumeContent checks that the user has those requirements and serves the content

Up to here the function could be a view, but not changing the status, the user still have the access rights to the content, and he can consume it every time that he wants, while the specification imposes once only.

We can modify this function to change the status and save that the user cannot access the content anymore. But this function is not a view, so the user have to:

  • send a transaction i.e. with contentContract.consumeContent({transaction})
  • call the function to retrive the content i.e. with contentContract.consumeContent.call({transaction})

But he can also just call the function, get the content and never do the transaction, so that he can access the content every time that he wants.

Any ideas? I have read a lot of topics about this, but for the moment nothing that suits this case.

So this statement is true?
"so I cannot recover the value returned by the function without having an event, that implies that a malicious user can watch on that event type and read all content."
There isn't a safer way?

Thank you in advance.

In reply to ALDO D'AQUINO

Re: How to force to use `send` instead of `call` in web3?

by DAMIANO DI FRANCESCO MAESA -

1) teh consume content should not return "the content" (for which you use the 'call'). What if teh content is music? Is your solution to implement a contract that returns an audio? I hope not! It clearly depends o your implementation but the consume normally would change the state (so transaction).

The couple (send transaction, call tarnsaction) makes no sense to me. In what case would it ever be correct (or even desired)? That is not how transactions are intended. I strongly advise NOT to do something like this (unless you are conviced and will be able to convince me during the exam...).

2) When I stated that the phrase "so I cannot recover the value returned by the function without having an event, that implies that a malicious user can watch on that event type and read all content." was strange is because it seems you miss the oint about a public blockchain. Saying "There isn't a safer way?" strengthen my doubt. What do you mean by "safer"? Dor emember that the blockchain is public!! Anyone can read everything. It is not "malicious" or "unsafe" to read content (transactions, contarct code, contarct data, etc), actually it is what users are supposed to do all the time to validate the state. There is no secrecy on the contract, you should remember that.

In reply to DAMIANO DI FRANCESCO MAESA

Re: How to force to use `send` instead of `call` in web3?

by ALESSANDRO PAGIARO -

So, if I've understood your point, we have to write: 

Catalog.grantAccess(content, user) that set a flag for content given the user to true (with some meaning)

Content.consumeContent(user) that reset that flag

And then, the use case is:

1) Catalog.grantAccess()

2) Content.getContent()

3) Content.consumeContent()

And even if I can consume a content is my honesty to declare it invoking the Content.consumeContent()? Because if I disjoin the Content.getContent() and the Content.consumeContent() potentially I can do something like:

GrantAccess()

getContent()

getContent()

getContent()

...

consumeContent() 

and no one will block me since the state invocation is done by me and is indipendent from the consuming.


In reply to ALESSANDRO PAGIARO

Re: How to force to use `send` instead of `call` in web3?

by ORLANDO LEOMBRUNI -

I have the same problem when testing on Ropsten directly from Remix. Consider the following simplified scenario:

contract X {
bool private granted;
bytes private content;

constructor (bytes _content) public {
granted = false;
content = _content;
}

function grant() public {
granted = true;
}

function consume() public returns(bytes) {
require(granted);
granted = false;
return content;
}
}

This is more or less a very simplified scheme of my implementation. Using Remix and the Javascript VM, clicking on grant() and then on consume() correctly does what is expected, including returning the content. Using Remix and the Ropsten network, the consume() operation correctly removes the grant, but does not return anything, as it should be since consume() is a state-modifying function. So, the question "how can the user access the byte array called content" arises because, as Aldo D'Aquino said, the only way to return values outside of contracts is to use events, and anyone can read the logs (so defeating the purpose of the paying system).

In reply to ORLANDO LEOMBRUNI

Re: How to force to use `send` instead of `call` in web3?

by DAMIANO DI FRANCESCO MAESA -

Because the issue is your idea that you return the content. Your mistake is to think taht, if you raise an event anyone can read it, but what about the contract? Anyone can already read teh content form the var

bytes private content;
it doesn't matter if it is privte, it is stored clear on the blockchain nevertheless! And the setup constructor invocation is a transaction written on chain as well.
It seams you do not get this point, there cannot be private data on Ethereum.

The content manager contract simply defines the acces control logic for an external frontend to read to decide wethere to show the content to a given user or not. In reality the actual consume will start in the frontend and then became a transaction to query nd update the contract.

In reply to DAMIANO DI FRANCESCO MAESA

Re: How to force to use `send` instead of `call` in web3?

by ORLANDO LEOMBRUNI -

Thank you, I misunderstood the purpose of the manager contracts and thought that they had to include the content data, even if it meant that the data would be public on the blockchain. Seeing them only as an access control mechanism for an external dApp makes much more sense.

In reply to ALESSANDRO PAGIARO

Re: How to force to use `send` instead of `call` in web3?

by DAMIANO DI FRANCESCO MAESA -

GrantAccess is GetContent (or a subroutine/part of it)!

If you do getContent multiple times, you pay each time, and you can then consume the content as many times as you paid (or just once if you want to simplify with booleans and refuse/ignore further payments).

"is my honesty to declare" ABSOLUTELY NOT. Nothing is left to aprticipants honesty in a trustless blockchcian distributed system. By default users are as dishonest as they can be.