spacemeshos / SMIPS

Spacemesh Improvement Proposals
https://spacemesh.io
Creative Commons Zero v1.0 Universal
7 stars 1 forks source link

SMIP-0012: Spacemesh Vaults - Multisig Operations - Interaction Design #40

Closed avive closed 1 year ago

avive commented 3 years ago

Spacemesh Vaults - Multi-sig operations Interaction Design

Background

In the use cases below, we have a multi-sig vault with Alice, Bob and Charlie as the master accounts for the vault (specified in spawn time).

Use Case 1: Withdrawing from a Multi-sig Vault using Web Service

  1. Alice and Bob agree to withdraw funds from the vault to another account.
  2. Alice uses a client such as Smapp or CLIWallet to prepare and sign a withdraw request message to Bob. The message should contain the following data:
    • Recipient account address.
    • Withdraw amount.
    • Signature scheme (e.g. ed25519 or ed25519++).
    • Alice full public key if signature format is ed25519.
    • Alice signature on the data above (using the private key corresponding to her vault master account address).
  3. Alice's client gives Alice an option to use a web service to send the message to one of the other master accounts holders, or to manually copy & paste the message and send it to Bob via another channel such as instant messaging or email.
  4. Alice decides she wants to use a web service to send the message to another master account holder.
  5. Alice's client prompts Alice to decide who should be the other signer - Bob or Charlie. Alice specifies Bob.

Note that this makes cleaning pending web service messages a bit simpler as only Bob can remove the message from the web service. If the message is not specifically to Bob or to Charlie, then it is not clear how messages can be removed from the web service easily without the web service monitoring the mesh for svm transactions. If the message is designated to Bob or Charlie then their clients will request the web service to remove the message on their behalf once they executed the transactions (or rejected it).

From a product perspective it is perfectly okay for release 0.3 to expect a mutli-sig vault user to request which party should sign a transaction he or she would like to do and not issue request that one of the other parties can sign.

  1. Alice's client submits the message to the web service api and displays the follow-up instructions:

Please ask Bob to open his wallet (Smapp or CLIWallet) and access your vault. He should see a request to execute this withdrawal and will be able to review and execute it.

  1. The web services stores the message indexed by the vault app address as well as the designated address (bob's master account address).

  2. Bob opens his client (Smapp or CLIWallet) and accesses the vault.

  3. Bob's client requests the web service for any pending messages designated to Bob for this vault.

  4. The web service returns Alice's signed request for withdrawal.

  5. Bob's client display the request details such as receiver address, amount and initiator address (Alice).

  6. Bob decides to execute the withdraw transaction.

  7. Bob's client prepares an SVM withdraw transaction which includes Alice's signed message and submits it to the network.

  8. Bob's client sends a message to the web service to remove the message from its store as it was handled by Bob. In addition, messages on the web services that were not removed should expire automatically after a reasonable TTL such as 3 weeks.

  9. SVM executes Bob transaction and verifies Alice's signature on the data in the calls params. The transaction is only executed if Alice's signature on the withdraw data can be verified.


Use Case 2: Withdrawing from a Multi-sig Vault without using Web Service

Same flow as use case 1 until step 4.

  1. Alice decides she wants to send the message to Bob directly.
  2. Alice's client copies the message's bin64 encoding to the clipboard and asks her to paste it in a channel with Bob. e.g. Instant message session or email.
  3. Alice's client provide these instructions to Alice: Send the message to Bob and ask him to open his vault in his wallet, select the 'Complete Transaction' command and paste the message he received from you when prompted.
  4. Alice sends the bin64-encoded message to Bob and communicates the instructions to him.
  5. Bob open his client (CLIWallet or Smapp), accesses the vault and chooses the 'Complete Transaction' command.
  6. Bob's client prompts Bob to paste a message.
  7. Bob pastes the bin64-encoded message Alice sent him.
  8. The interaction continues from User Case 1, Step 11.

Daily Spending Use Cases

The daily spending multi-sig operations such as change daily spending amount and change daily spending account should work in a similar way to the withdraw use cases described above. Bob's client need to know which operation a message confirms in order to present the correct UI and information for Bob to review and to sign.

Generalizing to multiple operations

tal-m commented 3 years ago

I don't think we need to have Alice say in advance who the second signer will be. The web service can delete the pending message if any of the following occurs:

In all cases, I recommend that the web service keep a "processed" message so Alice can tell what happened (and delete that when Alice acks, or after a timeout).

The "insecure" version (which is good enough for genesis, IMHO) is that the web service trusts Bob and Carol, so doesn't check if they actually sent anything to the mesh. In this case, Alice's smapp should check if the signed transaction is in the mempool (but even this is not critical for genesis --- Alice can check manually, and resend the transaction if she sees it wasn't submitted).

To support cases where Alice doesn't fully trust both Bob and Carol (e.g., when Bob might try to prevent the transaction from occurring), the web service can require that an "ack" consist of the fully signed transaction. In this case, the web service can submit it to the mempool itself, or let Alice do it.

avive commented 3 years ago

The fundamental problem with the insecure version is that it defeats the whole purpose of the multi-sig wallet because Charlie can write a simple script that removes new messages from the web services and thereby preventing bob from confirming. What I proposed solves this problem by having a designator party and only allowing that party to ack with a simple signed message so there's no need for the web service nor for the clients to interact with the mesh and the mem pool. BTW - you can't assume clients have access to a mem-pool or that the mem-pool they have access to has all pending transactions. It is a much better tradeoffs for the initial design and perfectly okay from a user perspective to have this limitation for 0.3. We can also design this so there's no need for messages removal because the client knows about all vault transactions and can ignore messages from the web services for transactions that already got executed and we just expire messages after few weeks. So to summarize:

avive commented 3 years ago

There's a usability and correctness problem if the message is not designated to only Bob or Charley - both open their client and sees a pending request to execute a transaction and they both naively execute a transaction with it - now both of their transactions are valid and cause a double-payment to the amount receiver if there's sufficient balance in the vault unless additional special logic is built to prevent this. By only designating the message to Bob or Charley we avoid this bad outcome altogether so I take back what I said in the comment above and the design in the full spec is better.

tal-m commented 3 years ago

Regarding the "insecurity" of the version I was talking about, it's a tradeoff between the trust assumptions and the UI changes (I'm trying to keep the UI exactly as it is currently designed). In most cases, Bob and Charlie are not adversarial, and trusting that neither will attempt to censor transactions might be a reasonable. After genesis, we can "upgrade" the backend to remove this assumption, without changing the frontend. (In the initial version, if there's a "censorship attack" by Bob, Alice can still use the manual backup method to send the request to Charlie, so it's not like Bob can completely prevent the transaction from going through --- only make it inconvenient).

Specifying who is allowed to cosign seems less scalable; when (eventually) our UI supports k-out-of-n for larger k and n, it's much less reasonable to specify exactly which k are allowed to cosign, so this would require a larger UI change.

The correctness problem you mention isn't as bad as it sounds: the transaction can't cause a double-spend because it has a nonce, and Bob and Charlie sign the same one. So even if both Bob and Charley sign and send transactions to the mempool, at most one can be executed. However, the gas could be deducted twice (if both make it in to the mesh), so it's not ideal.

The message-removal api is only an optimization for the web service (so that in the optimistic case it can use less memory), and indeed isn't necessary.

If you think it's fine to have the UI change a bit now, we might want to reverse the singing order, and have Alice sign the final transaction.

In this case, Alice posts an unsigned transaction to the web service and waits for either Bob or Charlie to sign it. She then adds her own signature and sends the transaction to the mesh. In this case, Alice doesn't care if both Bob and Charlie sign (separately), since she can just pick one of them. This scales very nicely to arbitrary k and n. Another advantage of this method is that the initiator of the transaction is responsible for the gas payment. The main disadvantage is that it's not "fire and forget" for Alice. She has to wait until the transaction is approved by Bob or Charlie, and then send it herself (of course, the smapp could take care of this automatically, but it would need to be online with a hot wallet to do so).

Since I expect multisig to be an extremely common use-case, it might make sense to make it more of a first-class object, in which case we can make signatures more symmetric, treat the same transaction with different signers as the same transaction (and possibly allow "simple" multisig transactions).

avive commented 3 years ago

Since we decided to not delay sm 0.2 with Smapp and webservice support for multi-sig and only make them work with copy & paste via CLI wallet, the consideration to try to built this in the way that current UI was designed is not an issue. Regardless, it involves major changes to current ui. I will update the interaction design based on the recommendation from research as expressed in Tal's comments and we'll take it from there.

avive commented 3 years ago

@noamnelke @tal-m - please talk and decide on the right underling flow in terms of preparation: A -> B -> A -> Submit or A -> B -> Submit. Once you do we'll design the UI to support this flow.

avive commented 3 years ago

ok, to finalize this smip, we'll go with the A signs a message, sends to B, B creates a transaction and submits. I'm going to finalize this SMIP and give it a number unless anyone likes to comment soon.

countvonzero commented 1 year ago

design made obsolete by current implementation https://github.com/spacemeshos/go-spacemesh/issues/3220