A Guide to Automated Signing of Stellar Multi-Sig Wallets
The GoodX Distributed Protocol
Multi-signature wallet is an acclaimed and popular Stellar wallet protection mechanism. Unfortunately, at this moment there is no convenient and practical way to create and sign Multi-signature transactions on the Stellar network, so it can only be done manually. Therefore, at GoodX Network, we developed a protocol based on the Stellar network that allows you to create and sign Multi-signature transactions in a simple and convenient way in semi-automatic mode.
Such a protocol has already been implemented in the GoodX application version 1.3 in the iOS. We are also going to add this protocol to the Android version of the application by the end of 2018.
The purpose of this article is to offer the GoodX MultiSig protocol to the community as a working solution for its implementation in various products which use the Stellar Blockchain.
Stellar is the main transport for sending a message between the participants of the Multi-signature wallet (MW). We consider the use of Stellar transactions unquestionably justified since the cost of transactions on the Stellar network is negligible and it is not even comparable to the effect of using MW.
Creating a wallet
Let’s imagine 3 participants: Ax, Bx, Cx — they want to create MW. Any participant that wants may become the initiator of the creation of the wallet. Stellar does not require confirmation from all the signatories to create an MW. Steps to this would be:
1. Create a new wallet on the Stellar network — Mx
2. Indicate signatories for Mx, wallets of three signatories, Ax, Bx, Cx, along with their weights.
3. Set the Master Weight for Mx to 0.
As a result, we get MW without the right to vote from the Master Key’s side but with control rights from Ax, Bx, Cx, according to the weights specified when creating the wallet.
To ease further explanation, consider user Ax as the initiator of creation of the MW. We also assume that the Ax, Bx, Cx wallets have the necessary XLM volume to complete the transactions described below.
Creation and the signing of a transaction
Let’s imagine that the user Ax is going to send 100 XLM to an arbitrary Stellar user — Zx. This is how it will be done:
1. Ax creates a Payment transaction from the Mx address to Zx and receives an XDR format of the Unsigned transaction.
2. Ax creates the HASH necessary for identification of this transaction in the process of its further signing by the following algorithm.
- calculate SHA-256 (XDR multisig of the transaction)
- take the first 8 Byte from the resulting SHA-256 and get TrxHash (8Byte)
- use the HEX format of TrxHash as the transaction identifier of TrxHashHex
3. We break HEX format of XDR of the required transaction into blocks of 64 Byte. BLOCK1, BLOCK2, BLOCK3.
4. Save the gained BLOCK1, BLOCK2, BLOCK3 in the DATA field of the Ax account under the names
5. Ax creates a transaction for the smallest possible transfer amount of 1 stroop and MEMO field using the GXSIGN<TrxHashHex> format, where GXSIGN is a sign that the sender Ax asks to sign a transaction with the <TrxHashHex> hash and sends to each of the remaining Bx, Cx signatories.
6. From here onward, Ax adds the Bx and Cx addresses in Watch Only mode and periodically checks the contents of the DATA fields for each one of them. While waiting for the DATA fields update with the specified TrxDataKey (described below) in the form of keys, and payload in the form of a signature for this transaction.
7. Bx and Cx, having received such a transaction demand request the value for the DATA fields from Ax, glue the XDR, decrypt and validate that Ax has the right to create the desired transaction (one of the Mx signatories).
8. Bx and Cx after successful validation, will sign the received XDR with their private key, and save the signature to the TxSig variable.
9. Bx and Cx calculate the 32byte transaction initiator key of Ax based on his/her public key. SUBSTR(BASE32_DECODE(Ax Publiic Key),2,-2) = TrxStartPubKey
10. Bx and Cx create the data to write in the DATA field of their account.
BASE64(SIG<TrxHash><TrxStartPubKey>) = 64 Byte = TrxDataKey
11. Bx and Cx save the TxSig in the DATA field of their Stellar account with the TrxDataKey key.
12. Bx and Cx begin to monitor the DATA field of the account of the initiator (Ax). As soon as Ax deletes the records for the required transaction from its DATA field, the transaction is either cancelled or completed. Which means that the Bx and Cx signatories can also delete their corresponding DATA fields.
13. As soon as Ax gets the minimum required number of signatures from the signatories, (s)he will create the final transaction. To accomplish this, at the end of the original (unsigned) transaction (XDR) the HEX is added: 00 00 00 0N where N = the number of signatures for this transaction. All signatures are added, including your own, in random order. *
14. The final transaction is sent to Stellar.
15. Ax — cleans the DATA field of his account associated with this transaction.
16. Bx and Cx also clean the DATA fields of their accounts.
* The signature in Stellar consists of 72 bytes
- the first 4 bytes are the last 4 bytes of the public key (the public key is the base32 encoded sequence of 35 bytes, in which the first is always 0x30, and the last 2 is the control sum, we need 4 bytes starting from the 30th).
- the next 4 bytes are the length of the signature; it is always 0x 00 00 00 40, i.e. it is 64 bytes.
- 64 bytes signature.
Plans & To-do
As is self-evident, this method can be used for multi-signature transactions in any blockchain, using Stellar as a decentralised, fast, robust, secure and nearly free transport for transmitting signatures for Bitcoin, Ethereum, etc.
We will be glad to see your feedback and comments on improving the protocol.