Skip to content

Instantly share code, notes, and snippets.

@nikhilsaraf
Last active October 11, 2018 19:13
Show Gist options
  • Save nikhilsaraf/b75ef572e75a1e8d1c0fa16eed54f018 to your computer and use it in GitHub Desktop.
Save nikhilsaraf/b75ef572e75a1e8d1c0fa16eed54f018 to your computer and use it in GitHub Desktop.
Stellar Multisig Coordination using SEP-0007

This proposal allows you to coordinate signatures from multisig enabled accounts using SEP-0007 style payment requests, iff the accounts opt-in to use this protocol. This would need support from wallet developers.

  1. All signers on your multisig account will need to have a Stellar Account associated with their public key. Accounts that want to use this protocol should have a data field multisig_uses_SEP-* to indicate that multisig is enabled for this account using this proposal (the * will be filled in once this is formalized into a SEP).
  2. Signers will have a data field, ex: multisig_coordinator that specifies a domain (example: mymultisigservice.com). The domain (mymultisigservice.com) will have a stellar.toml file that contains a field MULTISIG_ENDPOINT that lists an endpoint like so: https://mymultisigservice.com/multisig. This follows from SEP-0001 around the stellar.toml file
  3. When you sign a stellar transaction, your wallet will first check the multisig_uses_SEP-* field to check if the account can use this multisig coordination approach. It will then fetch the multisig coordinator service domain from the multisig_coordinator field on your own signer’s account (can be same as the source account) and will fetch the MULTISIG_ENDPOINT value from the domain's stellar.toml file. The wallet will then send a POST request to this MULTISIG_ENDPOINT with a signed version of the transaction XDR in a SEP-0007 format (using a tx operation).
  4. mymultisigservice.com multisig server will receive a request on its endpoint (https://mymultisigservice.com/multisig) and will pull the source account from the transaction XDR of the SEP-0007 request along with all the signers associated with that the account. It will then verify the signature to ensure that the request is from a valid signer. We can add the public key to the initial request to keep this verification step inexpensive.
  5. mymultisigservice.com multisig server will then create a callback endpoint (example: https://mymultisigservice.com/<uuid>) that is bound to this SEP-0007 request; this endpoint will collate signatures. mymultisigservice.com's multisig server is now the designated coordinator for this multisig request, i.e. it will submit the transaction to the network once it has collected and collated all signatures.
  6. mymultisigservice.com will fetch the MULTISIG_ENDPOINT for each signer on the account using the process described in step 2 and 3 above, and for each signer it will generate a new SEP-0007 request by appending the callback endpoint created in step 5 to the original SEP-0007 request using the callback field. It will also append the pubkey param with a value of the signer’s public key. All of this is provisioned for in the tx operation of SEP-0007. The list of signers should include any signers for specific operations in a transaction where the source account may differ from the transaction's source account.
  7. mymultisigservice.com will submit the new SEP-0007 request generated in step 6 to the MULTISIG_ENDPOINT associated with each signer. If the MULTISIG_ENDPOINT is the same for two different signers, this will constitute two separate requests, one for each signer. Note: these new requests should use signed SEP-0007 requests for an additional layer of security.
  8. someothermultisigservice.com will receive a SEP-0007 request and will first validate the request (similar to step 4) to ensure the signatures are valid against the source accounts. If the SEP-0007 request URI is a signed SEP-0007 request then it should validate the signature against the origin_domain (of mymultisigservice.com in this case) before proceeding ahead. It will then recognize that this request has a callback param. It will get a signature from the user by constructing yet another new SEP-0007 request, this time by updating the callback, pubkey, origin_domain, and signature fields. Once it has a signature from the user it will POST the signature back to the callback endpoint in the SEP-0007 request that it received (it will need to bind the callback it sends to the user's wallet with this original SEP-0007 request). The workflow in this scenario is very similar to receving a new request and it's implementation would ideally reflect that. Note: the user’s wallet will be responsible for checking with it’s own multisig_coordinator service for signature requests and this should be generalized into it’s own SEP. Wallets should present these requests for signatures for a multisig account in the same way that they would for any other SEP-0007 request.
  9. mymultisigservice.com will at some point receive all the signatures from the requests it sent out and should collate all these signatures into a single signed transaction, here's some sample code to help with signature collation. The process to handle redundant signatures or failure to receive all signautures will be defined later.
  10. mymultisigservice.com can then submit this transaction to the stellar network using the network_passphrase field on the original SEP-0007 request.

Here are some of the benefits of this approach:

  1. No need for a second layer network to coordinate multisig requests or signatures, everything is P2P between multisig servers.
  2. We make minimal use of the data fields on a Stellar account which keeps costs low (networking costs and network fees).
  3. supports SEP-0007 so we can make use of libraries that will handle SEP-0007 URIs as well as wallets that will implement UIs supporting SEP-0007.
  4. Signers can choose their own multisig coordination service and this will not introduce any dependencies between services.

Downsides:

  1. The downside of this approach is that each signer needs their own stellar account where they can maintain the multisig_coordinator field.
@stanford-scs
Copy link

High-level, while something like this makes sense, I think it won't necessarily be the only way to do it, so we need some demultiplexing convention, where some accounts use this approach, and others use different approaches (including potentially on-chain solutions such as those suggested in the PR I linked above).

@andywer
Copy link

andywer commented Oct 11, 2018

As we said in the call: We should not use UUIDs, but hashes, to make the submission idempotent.

@andywer
Copy link

andywer commented Oct 11, 2018

@stanford-scs Thanks for the link! We just talked about the idea to have a generic way of discovering multisig services using a data field on the account, but specifying the kind of service implementation in the stellar.toml.

@nikhilsaraf
Copy link
Author

^^specifically, UUID in point 5 above should be the hash of the original SEP-0007 request to serve as a unique identifier for the request instance across all signers.
This original SEP-0007 request can be considered to be the parent of all the other SEP-0007 requests created as a result by the multisig service and it should be fair to reference all child requests created by the multisig server with the key of (multisig_domain, signer_public_key, hash_of_original_sep-0007_request). This will provide determinism across all instances of a multisig service when trying to scale across different app servers and also when wallets try and fetch the latest requests for their account using a watermark cursor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment