A zkRollup with no transaction history data to enable secret smart contract execution with calldata efficiency

Could you clarify what would happen if the operator disappeared after publishing a batch without providing any state? How would users be able to withdraw their funds? In particular, what about liquidity providers that would need access to the latest state of token balances, which is part of the common state, in order to exit?

Here is the way to exit their fund.

This is the reason why only this account/ID lists could not be removed from txcalldata.

I see, but I’m more worried about losing the common state, since e.g. liquidity providers would need it in order to withdraw.

It won’t be a problem.
I’m sorry for the previous insufficient explanation. It’s different from the typical smart contract.

The transactor makes a transaction, and both the transactor and relevant LPs sign otherwise the diff will be on txcalldata.

Bacially, being online makes both the efficiency and the privacy.
ps: Offline user can have the privacy. I realized that the calldata messages of diff of offline user states can be encrypted for each of them with her public key, and off course this can be merged to her user state to exit with zkp.

Aha, I see. Would that mean that if even one LP, is offline, state diffs would need to be provided in calldata? I would suppose that would be the case most of the time in practice. Even so, it would still be an improvement, since the amount of diffs to common state is O(number of common contracts), which would be much smaller than O(number of users).

It’s up to how to code swap contract on this zkRollup.
One thing I can assure you is an offline LP with secret balance can not exist (edit: this was found to be possible, see the comment above), since the LP needs to make a zkp proof with her user state to keep it secret and this needs to be online available.

In one implementation, the diff of his state will be in calldata.

On Uniswap, especially V3, a swap transactor is having deals with LPs.
An LP locks their token on the contract and it’ll be added to the contracts’ balance on Ethereum L1,
the LP have their balance in his state with an allowance/flag controll for Uniswap contract on this zkRollup spec. These are same.

Another implementation is what you said, the final state of contract (commonly shared storage) will be in calldata. This would be safe as well.

I think online/offline requirements, secret/public, and usage of calldata will be programmable in this kind of network and VM. That’s why it’s up to how to implement contracts.

Also, have you seen this proposal? It seems relevant.

Yes, I did. And l think this seems a very good idea.
But it was different from my main focus, a secret smart contract execution with zkp and minimizing txcalldata of zkRollup with the same security assumption of zkRollup.

I believe the power users in Adamantium also enjoy the same security assumptions as a zk-rollup. The idea is the same; that you can avoid using calldata for online users.

Another question, if you don’t mind, because it is still not entirely clear to me:

Focusing on simple transfers, my proposal has the property that you can send funds to an offline recipient, without having to post the transfer data as calldata. When the recipient comes online, even in the worst case where they find out that their account state is unavailable, they can still exit by providing a witness to the latest balance they have, together with the receipt of the additional received funds (given to them by the sender).

How does your proposal handle this scenario? Do you require recievers to be online to avoid having to post the transfer in calldata?

I could not judge that, then I could not refer to Adamantium clearly.

If you cut out this part, you can say it’s the same about this part. Yes.

This does not simply occur.

It is easy to misunderstand the point of data availability in this protocol.

First, this protocol does not rely on off-chain decentralized storages. This is just an option.

I edited the document and added this.

Second, this is important that operators don’t need to write the commonly shared storage to calldata.

Let’s talk about the Uniswap V2 on this protocol spec, and let’s start with all LPs are online for the simplest case.
It’s essentially a transaction between a transactor and several LPs.

The secret smart contract execution of this Uniswap goes as below.

  1. The transactor send a transaction to the operator
  2. The operator send the diff of the commonly shared storage (like pooled amounts of ERC20 tokens and k-value) to the transactor and the LPs
  3. All of them make a zkp proof of the transitions of the Merkle roots of their user states caused by balance changes from that transaction. These can be receipts as well.
  4. The operator includes the proofs as the transactions in the next batch.

Then do you think it is dangerous that all nodes lose the commonly shared storage?

If it’s lost, the operators can not make a new transaction, then liveness will die. But anyone can exit her fund to L1 with the latest receipt. The service will end, but no fund will be compromised.

The commonly shared storage is needed for liveness, not safety.

1 Like

Thanks a lot for the idea to reduce the calldata size of zkRollup. I tried to understand the idea: instead of save transactions onchain, the state difference (the “commonly used” storage) is saved onchain only. Even the operator is crashed, he/she can recover the “common” state from onchain data. However, I have several questions in mind:
1/ Logically, if many transactions uses the same “commonly used” storage, the calldata size can be reduced. However, if each transaction affects different “commonly used” storage, the calldata size may NOT be reduced.
2/ Due to the fact, the “commonly used” storage for one batch of transactions is NOT fixed. To reduce the onchain size, extra circuit logic should be used. Whether the circuit complexity is increased?
3/ Because the “user used” storage is saved in user side, if the user lost his/her data, he can NOT send transaction anymore and the worst case is that he can NOT exit because he can NOT generate the according merkle proof.

Am I right about those understanding? Thanks a lot :slight_smile:

1 Like

Thank you

Actually, we can remove the common state difference from calldata without losing safety.
This is in the second step.

The common state diff can be shared off-chain, the circuit requires the operator to prove she shared the common state diff to other operators. Then one operator can not kill the liveness, and there will be no fund loss if it happens.

So only the account/ID list is needed to be in calldata, basically.
Almost all of txcalldata cost is removed from zkRollup if you allow the possibility of the end of the service and the relevant safe exit.

So here won’t be the problem. But you are right about the storage cost estimations of these cases when it’s discussed about off-chain data.

If he (and all other people) loses his user state data completely, he can not send any transaction anymore. You are right.

The best effort we can make for this is preventing the last user state update destroys the exit of the irrelevant assets in the user state.

Thanks a lot for your clarification. My understanding is that for best optimization, only changed account IDs are published on chain. And operators help to maintain commonly shared storage and users are on duty to save his/her user storage. For that case, the safety is NOT same as original zkRollup solution. For original zkRollup solution, the safety is exactly same as L1. However, your idea’s safety is NOT same as L1. Actually, the safety depends on operators’ safety. If all operators lost the “commonly shared storage”, the system has to enter exit mode and can NOT be recovered.

For this spec, safety is exactly same as L1 if users are online.
Liveness is not same as L1. That’s the difference.

Users don’t lose their money, and users don’t have double spend as far as L1 is not 51% attacked.
This is safety.

All assets can be exit since all of them are in “user state”.
Commonly shared storage should not describe the assets, and that’s why this spec separates these.
So, when “commonly shared storage” can not be recovered, safety will be fine. Liveness dies.

So the idea here is you allow users to withdraw from a previous state if a transaction for that address has not already been included ?

My concern here is that after a user has withdraw from an older state what stops that user from continuing to transfer funds that are already inside their rollup ? So the attack is that i withdraw from old state, transfer my funds on rollup to a new address withdraw again. I just doubled my money.

@adompeldorius this may also be applicable to your design ?

This is not an issue in my design, I replied here.

Exit makes new user state and also makes the account list include their address.
New transfer transaction from/to the address makes the account list include the address.

You don’t double your fund.

So if you create a block that contains a transaction from an address that has been withdrawn from an older state that block is invalid ?

Seems like this will make a potential dos attack where a user is able to front run a block creation and make its verification fail.

Such a consistency problem about exit can be solved by making “exit block” in certain intervals.
It’s a kind of a block only for exit transactions. If no block is mined in a period, maybe this interval needs to be 1; since this is the case that the operators are not able to mine a block anymore.