You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Summary or problem description
The topic of free/sponsored transactions had been touched several times by at least #1104, #1147, #1468, #2442 and neo-project/proposals#137. Some of those discussions are no longer relevant (the code evolved since), some tried to fix specific GAS claiming problems (like #2008 also), some are technically challenging to implement. We also had refueling capability (#2443/#2444) until recently which allowed for semi-sponsored transactions (with 0.000smth system fee paid by user and the rest by contract), but it turned out to be too problematic and went away with #2560.
At the same time given the number of related issues and questions on Discord (hi, @EdgeDLT) contract-sponsored transactions are somewhat expected of Neo N3 where every transaction has to be paid for and many dApps will happily pay for its users making it easier for them to use the dApp. And we do have some basis for them, that is support for multiple signers with scoped witnesses where the first signer (also known as sender) pays transaction fees.
So technically we already can create transactions with contract address specified as the first signer and then user address specified as the second one. If this transaction passes verification the contract will pay and the user will get what he wants. But verification relies on contract itself, specifically verify method of it that should decide whether transaction in question should allowed. For example, that's what Oracle contract does:
It considers to be valid any transaction that has OracleResponse attribute and this attribute itself is very special, to use it transaction needs to satisfy a lot of additional conditions:
So there is some responsibility sharing between contract and attribute which is possible because Oracle contract is native one. If someone is to try to do something similar with regular non-native contract he will discover that:
verification context is limited in GAS by MaxVerificationGas constant, so it can't use more than that for its logic:
If we're talking about generic sponsoring for untrusted users contract will definitely need to parse the entry script to only allow some specific ones (identifying its user at the same time and checking some internal user-specific conditions) and it will definitely need to check witness scope. But it can run out of GAS easily (even if it fits into the limit it will burn some in the process) and it can't differentiate between None and Global scopes for Sender which is very dangerous. It also of course can't test-execute the transaction to see the effect of it (notice that even manual multisignature collection allows for that, every member of committee can test-execute proposed transaction before signing it).
We get to the situation where even though we have all basic building blocks for transaction sponsoring we can't simply use them and get the result we want, something is still missing. If the decision on whether transaction should be sponsored or not can't be made in verification context it can be offloaded to some additional service. A contract can trust some (multi)signature of contract-specific backend and that backend will decide whether it signs transaction or not. The problem is that dApp needs to build this non-trivial app-specific centralized backend to accept partially signed transactions (and avoid being flooded with them), check them in whatever fashion, add missing signature and send to the network.
It can be done, yet at the same time it's challenging for dApp developers and every dApp that wants to do this will have to build corresponding infrastructure.
Do you have any solution you want to propose?
The same sponsoring issue is easily solved by the Notary subsystem proposed in #1573 and implemented in #2425. It also relies on multiple signers, but it's more flexible, not just contract address can be used for sender role, but any other GAS-holding app-specific address can be used as well thereby removing the need for contract to hold GAS. The actual decision on whether a transaction should be sponsored or not is made off-chain by nodes monitoring P2PNotary pools (like with nspcc-dev/neo-go#1984). These nodes don't have any GAS restrictions, they don't burn it while doing checks, they have absolutely all transaction's data, they can easily test-execute it to see if side-effects this transaction produces are expected ones and they just add some missing signature to transaction thereby making it valid and acceptable for the chain.
Of course it still requires some app-specific backend, but this backend can be sure it won't be flooded with partially-signed transactions (notary subsystem is protected from this), it can rely on the fact that these transactions already passed notary-specific correctness checks and both backend and frontend will work with the standard protocol, with no need to invent anything for this particular purpose. So while notary subsystem was designed for a bit different purpose originally it solves sponsoring too and seems to be the only practical solution to this problem at the moment.
This issue is an open problem-specific discussion though, feel free to throw in some new practical ideas for transaction sponsoring, the network really needs this.
Neo Version
Neo 3
Where in the software does this update applies to?
P2P (TCP)
SDK
The text was updated successfully, but these errors were encountered:
Summary or problem description
The topic of free/sponsored transactions had been touched several times by at least #1104, #1147, #1468, #2442 and neo-project/proposals#137. Some of those discussions are no longer relevant (the code evolved since), some tried to fix specific GAS claiming problems (like #2008 also), some are technically challenging to implement. We also had refueling capability (#2443/#2444) until recently which allowed for semi-sponsored transactions (with 0.000smth system fee paid by user and the rest by contract), but it turned out to be too problematic and went away with #2560.
At the same time given the number of related issues and questions on Discord (hi, @EdgeDLT) contract-sponsored transactions are somewhat expected of Neo N3 where every transaction has to be paid for and many dApps will happily pay for its users making it easier for them to use the dApp. And we do have some basis for them, that is support for multiple signers with scoped witnesses where the first signer (also known as sender) pays transaction fees.
So technically we already can create transactions with contract address specified as the first signer and then user address specified as the second one. If this transaction passes verification the contract will pay and the user will get what he wants. But verification relies on contract itself, specifically
verify
method of it that should decide whether transaction in question should allowed. For example, that's what Oracle contract does:neo/src/neo/SmartContract/Native/OracleContract.cs
Lines 259 to 263 in a48e79a
It considers to be valid any transaction that has
OracleResponse
attribute and this attribute itself is very special, to use it transaction needs to satisfy a lot of additional conditions:neo/src/neo/Network/P2P/Payloads/OracleResponse.cs
Lines 85 to 94 in a48e79a
So there is some responsibility sharing between contract and attribute which is possible because Oracle contract is native one. If someone is to try to do something similar with regular non-native contract he will discover that:
neo/src/neo/SmartContract/Helper.cs
Lines 21 to 24 in a48e79a
If we're talking about generic sponsoring for untrusted users contract will definitely need to parse the entry script to only allow some specific ones (identifying its user at the same time and checking some internal user-specific conditions) and it will definitely need to check witness scope. But it can run out of GAS easily (even if it fits into the limit it will burn some in the process) and it can't differentiate between
None
andGlobal
scopes forSender
which is very dangerous. It also of course can't test-execute the transaction to see the effect of it (notice that even manual multisignature collection allows for that, every member of committee can test-execute proposed transaction before signing it).We get to the situation where even though we have all basic building blocks for transaction sponsoring we can't simply use them and get the result we want, something is still missing. If the decision on whether transaction should be sponsored or not can't be made in verification context it can be offloaded to some additional service. A contract can trust some (multi)signature of contract-specific backend and that backend will decide whether it signs transaction or not. The problem is that dApp needs to build this non-trivial app-specific centralized backend to accept partially signed transactions (and avoid being flooded with them), check them in whatever fashion, add missing signature and send to the network.
It can be done, yet at the same time it's challenging for dApp developers and every dApp that wants to do this will have to build corresponding infrastructure.
Do you have any solution you want to propose?
The same sponsoring issue is easily solved by the Notary subsystem proposed in #1573 and implemented in #2425. It also relies on multiple signers, but it's more flexible, not just contract address can be used for sender role, but any other GAS-holding app-specific address can be used as well thereby removing the need for contract to hold GAS. The actual decision on whether a transaction should be sponsored or not is made off-chain by nodes monitoring P2PNotary pools (like with nspcc-dev/neo-go#1984). These nodes don't have any GAS restrictions, they don't burn it while doing checks, they have absolutely all transaction's data, they can easily test-execute it to see if side-effects this transaction produces are expected ones and they just add some missing signature to transaction thereby making it valid and acceptable for the chain.
Of course it still requires some app-specific backend, but this backend can be sure it won't be flooded with partially-signed transactions (notary subsystem is protected from this), it can rely on the fact that these transactions already passed notary-specific correctness checks and both backend and frontend will work with the standard protocol, with no need to invent anything for this particular purpose. So while notary subsystem was designed for a bit different purpose originally it solves sponsoring too and seems to be the only practical solution to this problem at the moment.
This issue is an open problem-specific discussion though, feel free to throw in some new practical ideas for transaction sponsoring, the network really needs this.
Neo Version
Where in the software does this update applies to?
The text was updated successfully, but these errors were encountered: