Skip to content
Switch branches/tags
Go to file
Cannot retrieve contributors at this time


SEP: 0021
Title: On-chain signature & transaction sharing
Author: Mister.Ticot
Track: Informational
Status: Draft
Created: 2018-08-31

(Personal note: this is the first time I'm doing a protocol proposal. Please be helpful if you think something is wrong or missing. Also I'm not a native English speaker and I'll appreciate any help to make this document clearer.)

Simple Summary

This SEP define a standard way to share signatures and transaction directly on any Stellar blockchain. This is to complement the on-chain multi-signature account setup available directly in Stellar Core.

Status of this SEP

This SEP is a draft and is open for further discussion. Those condition should be met before approval:

  • The reference implementation fully implement the present protocol. [DONE]
  • Any security / critical issue that would be found by reviewers are solved.
  • We define a default network for signature & transaction sharing.

The expected delay to meet those condition is one month (from creation).


Multi-signature account setup and multi-operation with multi-sources transactions are directly supported by Stellar Core. Finding a way to keep the multiple involved parties is left to wallet/services developers. However, if each developer do it its own way, there's no compatibility and while the feature is technically available it won't become practically available.

This calls for a simple and well-defined protocol of how one can share signatures and transactions between co-signers.

There's two potentially overlapping cases were signature and transaction sharing makes sense:

  • For account with multiple signers
  • For transactions with multiple sources

It is desirable handle signatures collection / transaction sharing in a reliable, transparent and resilient manner. There are several good reason to implement this directly on the Stellar blockchain:

  • We don't rely on any external software.
  • We use a well-tested and well-known solution.
  • We automatically get strong security, transparency, decentralization, resilience.
  • Signatures can stay for ever (important for some smart contracts implementations).
  • This is elegant.


For the sake of clarity, the following terms will always be used as defined here:

  • primary source: The account for which signature and transaction sharing may be enabled. In context of a transaction, the primary source account.
  • sources (plural): Refer to the whole set of sources for a particular transaction. A transaction can have more than one source because each of its operation can have its own source.
  • source network: The network on which primary source exists.
  • legit signer: For a account, it is a public key or a preimage registered as signer. For a transaction, it is an account or a preimage registered as signer for one or more sources.
  • legit signers (plural): Refer to the whole set of possible legit signer.
  • collection account: The account dedicated to the task of "receiving" signatures and transactions.
  • collection network: The network on which collection account exists. This may or may not be the same than source network.
  • mirror account: When source network and collection network are different, the account with the same public key legit signers create on collection network. When source network and collection network are the same, mirror account is to be taken as any legit signer account.
  • main transaction: The transaction that we could share, and for which we could share signatures.
  • sharing transaction: A transaction that embed signatures or a transaction to be shared.


The present standard is network-agnostic. While a default collection network is to be defined in case user doesn't provide one, it is compatible with public network, test network and any standard Stellar custom/private network. User is free to choose to use any of them according to its needs. Signature and transaction sharing doesn't have to happen on source network.

The data is stored and accessed via collection account transaction history. First, collection account is created for this sole purpose. Then, signatures and transactions can be "sent" to collection account by creating a transaction made of a minimal payment to it, and one or more manageData operations embedding the data. The data can be retrieved by fetching collection account history.

On-chain signature & transaction sharing configuration

On-chain signature & transaction sharing configuration is stored in primary source data entries. There's three of them: config:multisig, config:multisig:network & config:multisig:server. The two last are optional.

On-chain signature & transaction sharing is enabled for primary source when it have the config:multisig account entry set. Its value should be the public key of collection account. However, the present protocol could be extended by accepting another type of value here, so we could support off-chain signature & transaction sharing scheme at a later time. If config:multisig is set but is not a Stellar public key, implementation should emit an exception that account for this possibility, like :

The requested signature & transaction sharing method is not supported or is invalid: expected 'config:multisig' to be a Stellar account Id.

Optionally, collection network can be defined in the config:multisig:network account entry. This should be either 'public', 'test' or any valid network passphrase. If defined, implementators must use the requested network. Else, implementators must use the default network.

The config:multisig:server is for specifying an horizon server URL. If specified, implementation must use it. An exception must be thrown if it is not set when a custom network is set up (any network passphrase that is not the one for test or public network).

Enabling on-chain signature & transaction sharing

collection account should be an account created for the sole purpose of signature & transaction sharing. The secret seed should be destroyed after keypair generation. A typical transaction to enable on-chain signature & transaction sharing is:

(on **source network**)
source: **primary source**
  - manageData: set account entry 'config:multisig' to '**collection account** accountId'
  (optionaly set 'config:multisig:network' and 'config:multisig:server')

In order to send signatures & transactions, collection account and mirror accounts have to be created, and mirror accounts have to be able to pay for transaction fees. This could be done at this step, or the first time data is sent. (The reference implementation does it first time data is sent.)

This protocol is said enabled for a transaction when and only when its primary source enabled it. In that case, any party must share signatures according to the primary source configuration regardless of the fact they enabled the protocol on their own account. Conversely, if the primary source of a transaction has not enabled the protocol, none of the party should make use of it even if they enabled it on their own account.

Disable on-chain signature & transaction sharing

All the account entries related to signature & transaction sharing must be unset.

(on **source network**)
source: **source account**
  - manageData: unset account entry 'config:multisig'
  (unset 'config:multisig:network' and 'config:multisig:server' when relevant)

Sending transactions

The purpose of sending a transaction to collection account is to share transaction requests between co-signers of primary source. It is by no means a way for an external actor to send transaction request. However, anybody can listen to transaction requests and it is possible for external actor that may have to participate into multi-source transactions to listen and retrieve transaction requests.

The main transaction XDR (without signatures) is split into chunks of 64bits and each chunk is sequentially embedded into a manageData operation. The name of the manageData operation must be 'Send'. The sharing transaction memo is a hash memo set to the main transaction hash. The sharing transaction source must be a legit signer for primary source else an exception must be thrown.

(on **collection network**)
source: **mirror account**
memo: (hash) transaction hash
  - Send 0.0000001 XLM to **collection account**
  - Set data entry 'Send' to '{transaction_chunk1}'
  - Set data entry 'Send' to '{transaction_chunk2}'
  - Set data entry 'Send' to '{transaction_chunkN}'

Fetching transactions

collection account transaction history is scanned backward for transactions with 'hash' memo. When those are encountered, and only if its source is a primary source legit signer, the record is retrieved and the transaction re-built from chunks. Implementators may save the ledger cursor to differentiate between requests which have already been presented to the user and new requests.

Sending signatures

mirror account send a sharing transaction with a rethash memo set to the txHash of the signed transaction. One payment or createAccount operation set collection account as destination, so the transaction will figure in collection account transaction history. One or more operation
manageData operations set a data entry whose name starts is 'Send' to the value of signatures.


(on **collection network**)
source: **mirror account**
memo: (rethash) {transaction_hash}
  - Send 0.0000001 XLM to **collection account**
  - Set data entry 'Send' to '{signature1_value}'
  - Set data entry 'Send' to '{signature2_value}'

Implementators must only send signatures that haven't been shared yet.

Fetching signatures for a specific transaction

collection account transaction history is scanned backward for sharing transactions with rethash memo equal to the hash main transaction and source being one of the legit signers. Each matched sharing transaction is scanned for manageData operations which set an account entry named 'Send', and retrieve the associated value as a possible signature. A signature is considered legit and must be used only when it is from a legit signer.

Default collection network

Specifying a default collection network allow to skip setting 'conf:multisig:network' in most case. The default collection network have to be specified in the present SEP so that every implementation use the same.

At that time the reference implementation is set to use test network by default. The advantage of using test network are: it exists, it is free to use, it is maintained by the SDF. The disadvantage is that it may get reset at some point.

Using public network as the default have the advantage of robustness, but come with a cost and would burden the network. It seems better to only leave the option open for when it is really meaningful (smart contracts).

Running a custom network seems ideal, however this makes sense only if we can keep it running smoothly on the long run. It means a core of validator have to take on this task. It also imply a cost in money and time.

Reviewers are welcome to discuss this issue so we can make a clever decision in the coming month.

Allowing external transaction requests

In this standard, only the co-signers of primary account are allowed to share transactions in the scope of managing the account together. However, one or more signer(s) with powerless summed weights might be added to primary account for the purpose of allowing them to pass transaction requests.


The implementator is free to make any relevant optimization over this protocol, as long as it doesn't alter its functioning. In particular, retrieved data may be cached and cursors or ledger values may be used in order to differentiate between data which have already been presented to the user and data which have not, and to speed up retrieving process.

Possible drawbacks

A few drawbacks have been pointed:

  • It is slower than off-chain solution (one update every 5s).

If a high-speed synchronization is needed, an off-chain solution is clearly preferable. However, most use cases can be properly handled with the present protocol.

  • It may become a burden because of data weight (if using public network).
  • It comes with a cost (when using public network).

Using public network (and thus paying fees) seems desirable in some specific use cases like smart contract implementation. This protocol is indeed an interesting alternative to pre-signed transaction, as there's no limit to the number of pre-signed transaction. Also, the signature cannot be removed after being shared while pre-signed transaction setup can eventually be changed.

Having a free-to-use dedicated default network will make the present protocol useful as well for every user.

Possible attacks

From external actors

A malicious actor could send a bunch of transaction to collection account in order to make legit data retrieving slower. However, this won't prevent it and primary source can later switch to a new collection account simply by changing multisig:conf, which make this attack of few interest.

External actors haven't any other possibility, as transaction and signatures are only retrieved when shared by legit signers.

From co-signers

A malicious legit signers could send wrongly-formatted data in an attempt to trigger exception the protocol implementation and stop the data retrieving process. This could be used to prevent retrieval of signatures for a transaction that would have a negative impact of this malicious actor. For this reason, implementators have to make sure any wrongly-formatted transaction is handled properly.

Implementators should also avoid using main transaction request as the breaking point when retrieving signatures for main transaction, as a malicious legit signer could leverage this behavior by sending a second main transaction request to shadow some signatures. While implementators should not allow this behavior, this is still possible to do by other means.