Phase 2 pre-spec: cross-shard mechanics

The pre-spec introduces a number of discussions:

Discoverability

How can the CROSS_SHARD_MESSAGE_RECEIVER be accepted in the destination shard?

Possible solutions may be:

Sender submits the call as a second transaction

  • Mechanism: original sender will wait for finality on the beacon chain then submit a receive transaction on the receiving shard. This transaction requires gas submitted (without an inherent crossover from the other shard) since merkle proof verification is a non-trivial operation and the node needs an incentive to run the witness verification.
  • Pros: sender has control over when the transaction is received in addition to gas prices, etc…
  • Issues: The sender likely has no funds on the receiving shard and for this reason is submitting a cross shard transaction.

Wallet provider submits the call on behalf of the sender

  • Mechanism: The wallet provider has a balance on the receiving shard and therefore submits the transaction on behalf of the user. The wallet provider would calculate the gas needed ahead of time and subtract it from the balance of the user on the source shard. For this solution to work, there must be a system in place to submit a receiving transaction on behalf of the original sender in the receiving contract. This should be trivial. Otherwise it could be included within the account abstraction model.
  • Pros: Better UX for the user and avoids liveliness requirements on behalf of the user.
  • Issues: Wallet providers must carry balances on all shards to issue transactions on behalf of users. This may also expose various attacks on wallet providers. Additionally, users must trust and rely on the liveliness of wallet providers to submit the receiving transaction.

Incentive Mechanism for Others to Submit the transaction

  • Mechanism: Certain watchers or programs monitor all the shards for a CrossShardReceipt. When detected, the watchers monitor for finality and verify the transaction independently. If verified, they submit the receive transaction to the receiving shard on behalf of the original sender. Upon completion of the transaction, the watcher should receive a payment from the originator. This would either require additional arguments that state how much of the msg.value is reserved for incentives and would need to be reflected in the receipt. Alternatively, the sender could include a higher gas amount which is carried over to the receiving shard with the remaining gas being routed to the incentive provider.
  • Pros: Reduces liveliness requirements of the original sender. Incentive mechanisms could make for a more distributed solution.
  • Issues: Significant complexity and changes to implement. Attack vectors against the original sender where the block provider makes a deal with the watchers to prioritize against the original transaction sender’s submission. This can be mitigated against by having a flag on the CrossShardReceipt which states whether the user wants an incentive submission or not. Mempools may begin to be flooded by competing incentive providers to submit on behalf of the users.

Beacon Chain maintains receipt records of withdrawals and CrossShardReceipts

  • Mechanism: Shard nodes must keep a full trie receipt record for a certain period of time from the beacon chain. When the block proposer is building a new block, its mempool may contain regular transactions and messages linked via the beacon chain receipts trie. This reduces the need for the block provider to run a merkle proof on the CrossShardReceipt. It would also require gas to carry over from the source shard or the receipt to contain its own gas values that are extracted from the original msg.value.
  • Pros: Does not require third party involvement, mempool flooding, or original user liveliness. Finality is committed to the beacon chain and can abstract the behavior of cross shard transactions to follow the exact same mechanism as a withdrawal.
  • Issues: Duplicating storage on beacon nodes and shard nodes. Complexity involved on incentive mechanism/gas payment. Remaining gas would be burnt or distributed to the original sender’s account address on the receiving shard. This could essentially begin forming dust across all the shards. Also brings to question what happens if there is not sufficient gas? Can the original sender rollback the CrossShardReceipt? Can the sender submit the transaction with additional gas in the case of a mistake?

Attack Vectors

Some vulnerabilities form due to the approaches above:

  • In the Incentive Mechanism or Beacon Chain approach above, the sender can create a lock on a contract yank by not including enough of an incentive for the transaction to ever be included in the receiving shard. In order to recover from this issue, another user must pay and submit the transaction on behalf of the original sender.
  • One discussion - Cross-shard contract yanking suggests receipts must live for a year. If I submit the original send/call transaction and I am not aware of the gas fees/limits on the other shard and thus my transaction is never received, should I be able to cancel the original yank or send call to recover funds on the original shard? If I miss the timeframe, are my funds lost or is the CrossShardReceipt rolled back?
  • See issues in above section for other attack vector discussions

Opcode Requirements

Both the CROSS_SHARD_MESSAGE_SENDER and CROSS_SHARD_MESSAGE_RECEIVER require special privileges. For example, the sender may reduce balance not related to execution and may also destruct an existing account. In the case of burning funds, is this just a regular send command? In the case of destructing an account (related to yanking) do we maintain the SELFDESTRUCT command with additional ruling provided to the EEI function or do we introduce a separate opcode?

On the other end, the receiver may also have special privileges. In the pre-spec, there is discussion of initiation data. One thing that was not clear is whether this behavior will be allowed only for the receiver contract or if there is an expanded contract creation opcode to manage contract initiation with pre-existing storage? If so, the difference between the method by the receiver would be its ability to arbitrarily pick an address vs. enforcement of target = hash(salt, hash(code) + hash(storage))? Or is this behavior only reserved for a receiver? If so, a special opcode would also need to be implemented in this case. If this behavior is not only reserved for the receiver, an opcode would need special behavior if the receiver address is calling the opcode, yes?