Query calls are free (in cycles) for now. Eventually, once we agree on a way to filter out outliers (malicious nodes) and find the time to implement it, they should be charged for, as they are very much not free in terms of compute (and, if you look at canisters issuing downstream queries to other canisters, in some ways more expensive than updates).
Probably a more sane solution would be for boundary nodes to only route queries to “up-to-date” replicas (which must be at least 2/3 + 1 of them, so there is still room for randomly picking one). This could either be done deterministically (“continuously” poll all replicas and only route queries to those that are at the maximum block height) or optimistically (poll replicas at reasonable intervals, e.g. 10 seconds, and only route queries to those that were up to date when last polled). The latter is probably sufficient, as there is no guarantee that any given replica isn’t malicious and e.g. lying about its height or just returning garbage regardless.
(and, if you look at canisters issuing downstream queries to other canisters, in some ways more expensive than updates).
Am I reading this right that if a canister makes an inter-canister call to another canister’s query method (which still goes through consensus like a regular update call), that calling canister will NOT be charged cycles?
But if the called method was instead an update method, then it would be charged?
No, all calls that go through consensus (and end up in a block) are charged for just the same, regardless of whether the called method is labeled as a query or as an update.
Query calls to query methods are currently not charged for, because a malicious replica might claim that any number of query calls have been made to any given canister, unilaterally causing arbitrarily large charges to the canister. We couldn’t reach agreement regarding how to filter out potentially fraudulent charges, so queries are free for the time being.
But the main idea would be to essentially eliminate outliers (whether malicious or not) and charge based on the traffic seen by e.g. the 25th to 75th percentile.
On other idea I remember hearing about in order to actually detect malicious replicas would be for some (small) proportion of queries to be routed to two replicas instead of one. As long as the two queries are served based on the same state (i.e. at the same height) one could compare responses (or hashes thereof) and record any inconsistencies.
I guess the main reason why nothing was attempted in this direction yet is that it was not deemed important enough (compared to other work that needs doing) and so no one had time to look into it beyond a chat over lunch,