As you may know I've been mentionning this here and there since I came around in january. While being on my way to implement this I noticed I'm not the only one working on that anymore. So, I'd rather open the thinking process now. The aim is to see if we can agree on a solution satisfying enough.
Stellar is a step ahead when it comes to multisignatures, as all setting up operations are handled natively on the blockain, allowing for a wide variety of configurations. However, the signature collection is not part of the scheme so we had to rely on old-school servers with all their known pitfalls. It is possible to move the signature collection process to the blockchain itself and I'll try here to expose a solution for that.
Goal
When several parties are signing a transaction for a shared account, we want that:
- Each signer can send its signature to the collection service
- Each signer who happens to get a signature from someone else can send it to the collection service aswell
- Each signer can witness the process
- Nobody can delete or modify collected signature
- Anyone can gather the signatures and attempt to validate the transaction
- Non-legit signers can't participate in the process
- Nobody owns or rule over the collection service
- It should be efficient
Those goals fit very well what blockchain technology have to offer.
Attaching datas to transactions
Assuming that each signer can already access the transaction to be signed, a minimum of two pieces of datas have to send to the blockchain:
- The hash of the signed transaction
- A signature
- It could be desirable to be able to attach more signatures in some cases.
A Stellar transaction allow for a memo where a transaction hash can fit.
The manageData operation allows to set an entry field to a 64 bytes value, which is exactly the size of a signature.
An additional payment operation with the minimum amount is needed to define a recipient for this transaction. The recipient will be the account where the signatures are collected.
Collecting account
Ideally, this would be a dedicated account, that nobody use, and that would be attached to only one account . This way, we minimize the number of transactions to go through when looking for signatures. Stellar horizon servers arn't exposing a way to select a transaction by memo, so this is important if we want to keep good performances.
This collecting account should be recorded as an entry into the main account; So the signers would have to meet the threshold to set it up / change it / disable it. In this setup, I would recommend that the lowThreshold, which rules upon manageData operation, is set at the same level than the midThreshold, that rules over most transactions except adding/removing signers.
I propose that we use an entry named "config:signature_sharing" to store the publicKey of the collecting account.
Fetching signatures
Getting the signatures from the transactions on the collecting account is simple enough. One have to filter them by memo, then get the value out of manageData operations. As we don't send any hint about the signature emitter, and as we want that signers can transmit signatures from other members as well, we simply have to try each signature against each signer to find which match. This scheme allow transmitting of hash signatures as well which is a must-have.
This should be noted that only transactions sended by legit signers to the collecting account should be fetched for this operation.
Additional side-effect
This setup also allows to handle cases were several single signatures account are involved in a multiple-operation transactions, like in smart contracts. In which case, each signers could share its signatures if the transaction source have the protocol enabled.
Pitfalls
- Setting this up may require signature collection which have to be handled another way (i.e.: XDR copying); For new accounts, it is adviseable to enable onchain signature collection first, add co-signers then.
- Account master key can't send its signatures as it would mess with sequence number and require multisignature itself. However, it can gather signatures and validate. Ideally, the master key of a shared account would be put to 0 for simplicity.
- Stellar protocol currently reject transaction with "too much" valid signatures, which's something we'll have to work around. Getting the exact right number of signatures may be tricky. Anyway this is true for multisig in general and it's not specific to the present proposal.
- It is not clear whether the Stellar Foundation welcome hosting datas on the blockchain; I told them about my plans and I'm currently waiting for news (doesn't looks like I'll get any).
That's all folks!
Hopefully this is consensual and simple enough so we can get a standard out of it. I'm actually coding the javascript library that will handle it and I hope to present a reference implementation soon enough.
A next step would be to use a similar design to setup a transaction collecting account, where transaction XDR could be shared between legit signers. This would complete the scheme and allow us to have a really secure and complete solution for multisigning on the Stellar blockchain.
If you have any comment to do on this please go ahead so we tackle anything I would have missed.