Skip to content

Instantly share code, notes, and snippets.

@AdamISZ
Created April 27, 2019 15:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save AdamISZ/fb08b5e341c1fa024831ef035ba2c2a6 to your computer and use it in GitHub Desktop.
Save AdamISZ/fb08b5e341c1fa024831ef035ba2c2a6 to your computer and use it in GitHub Desktop.
Multiparty symmetrical Schnorrr scriptless script swap (SSSSS)

General idea; generalise the Schnorr scriptless script atomic swap of A Poelstra to multiple parties.

We consider 3-party case with trivial generalisation. Parties are Alice, Bob, Charlie, A, B, C. Payment destinations are D_x. Transactions are TX_x. Adaptor signature secrets are t_x (scalar), T_x (point). Signatures are "sigma", adaptor signatures will be marked with '.

( Before we begin, relevant reading:

  1. My blog post on the Schnorr signature scriptless script atomic swap: https://joinmarket.me/blog/blog/flipping-the-scriptless-script-on-schnorr/ ; note that much of the following will not make sense unless you understand the definition of 'adaptor signature' explained there in detail. )

Phase 1 - Setup

The 3 parties create 3 x 3 of 3 Schnorr mulitisig destinations D_A, D_B, D_C in the accepted style (musig, let's say). Subscripts A, B, C are to denote the intended spender into this address.

The 3 parties all provide signatures on backout transactions such that each party respectively gets their money back before a timeout. See the section below "Timing controls" for more details on this.

The 3 parties then can safely fund the expected amount (say 1 coin for now) into their agreed destinations.

After confirms of these pay-ins, we proceed to phase 2.

Also, the parties agree on a permutation of payments from D_A, D_B, D_C. For example: D_A could pay B 1 coin, D_B could pay C 1 coin, D_C could pay A 1 coin. We'll call these TX_A, TX_B, TX_C.

Phase 2 - Adaptors

Each participant chooses their adaptor secret t_A, t_B and t_C and then share T_A, T_B, T_C with other 2. They then also all provide adaptor signatures on each of 3 transactions TX_A, TX_B, TX_C. (Technicall a completely all-tell-all of adaptor signatures is not necessary, but is simplest and hurts nothing, I believe).

Concretely, that would mean something like:

  • Alice provides sigma_A_A', sigma_A_B', sigma_A_C' where the first subscript is for the creator of the signature, and the second subscript refers to the transaction from D_X (D_A, D_B, D_C as described in Phase 1). She provides these three to both Bob and Charlie, at the start. There is no risk for her in doing so.
  • Bob provides sigma_B_A', sigma_B_B', sigma_B_C' to Alice and Charlie.
  • Charlie provides sigma_C_A', sigma_C_B', sigma_C_C' to Alice and Bob.

Verification: each party must confirm that the adaptor signatures "verify" against each of the three txs TX_A, TX_B, TX_C (where "verify" of an adaptor signature is obviously not literally signature verification, this point is explained in my earlier blog linked above), and that they match T_A, T_B and T_C respectively. Crucially of course, each party must verify that the same T_x adaptor secret (point) is shared across each of the three signatures given by each of the other parties.

So for example, Bob will verify sigma_A_A', sigma_A_B', sigma_A_C' adaptors all match T_A and work for transactions TX_A, TX_B and TX_C, and will verify that sigma_C_A', sigma_C_B', sigma_C_C' adaptors all match T_C and work for transactions TX_A, TX_B and TX_C respectively.

If there is any communication breakdown during this process, or verification failure, there is no risk to any party; they wait to reclaim funds via the backout transactions that were pre-signed (see "Timing controls" below).

We should now have the property that the broadcast of any 1 of the 3 transactions reveals in aggregation all adaptor secrets to all parties, so all transactions can (and will be) broadcast by their recipients.

Important note - remembering that Schnorr signatures aggregate, we can see that a broadcast of e.g. TX_A, when one party has already handed over their signature for it, say Alice, so Alice has handed over sigma_A_A, will not necessarily reveal individual adaptor secrets t_B and t_C, but will reveal their sum; Alice can simply subtract her own signature sigma_A_A from the final complete signature sigma, then subtract from that, the adaptors of each of Bob and Charlie, this will reveal the sum t_B and t_C although it will not reveal each individually, and this will be enough to form a valid completion on other transactions TX_B, TX_C.

Note how this generalises to any number, because adaptor signatures, like Schnorr signatures, are linear; the sum of adaptor signatures is an adaptor signature. So for 10 parties, I can essentially treat the other 9 parties as a single aggregated counterparty.

Phase 3 - Execution

We deliberately ignore the safe ordering of events here, until the next section. This is just a randomly ordered example of completion.

Now Alice and Charlie, for example, having both successfully verified, can pass valid full signatures (or equivalently adaptor secrets) sigma_A_A, sigma_C_A (TX_A pays Bob) to Bob. Bob will broadcast and receive 1 coin.

Alice will read sigma_C_A + sigma_B_A from the broadcast transaction and deduce, by subtraction, the value of t_C + t_B. (or the parties may voluntarily share individual adaptor secrets of course). Possessing t_C + t_B, she can create a complete sigma_C_C + sigma_B_C (TX_C is the one that pays Alice).

Charlie will read sigma_A_A + sigma_B_A from the broadcast transactoin and deduce, by subtraction, the value of t_A + t_B. Possessing t_A + t_B, he can create a complete sigma_A_B + sigma_B_B (TX_B is the one that pays Charlie).

Thus both other parties were able to claim their coin by creating complete signatures by combining the adaptor signatures with the revealed (possibly aggregated) adaptor secrets.

Timing controls

In the 2 party swap (see blog post above), as in earlier CoinSwap designs, we simply account for the asymmetry of secret knowledge using an asymmetry of timelocks. The one who transfers something valuable first (a signature) must have an earlier ability to refund coins that are "stuck" due to protocol non-completion, else the possessor of the adaptor secret / coinswap secret, who does not reveal it first, may wait for the window where he can reclaim and the other cannot, to both reclaim and use the secret to steal the other's coins.

Here we must follow a similar principle, just extended to multiple parties.

Suppose naively we just used the same locktime on each of the three refund transactions.

Now suppose Alice, at the start of Phase 2, reveals her signature (full, not adaptor) first on transaction TX_A which pays Bob. And suppose for maximal pessimism that Bob and Charlie are colluding to defraud Alice. They will simply wait until the moment of the timeout and attempt to cheat Alice: try to broadcast both of their own refunds, while spending the transaction for which Alice provided the full signature (having done so, she has revealed her adaptor secret to the other two).

Thus by instead making Alice's backout locktime the earliest, she is safe in transferring her full signature, and thus her adaptor secret first. In this case if Bob and Charlie collude, they can do no better than publish this spend before that (earliest) timeout, and in so doing, reveal the aggregate of their adaptor secrets atomically so Alice can claim her money well before their backouts become active, as intended by system design.

Now let's consider the second sender of a full signature, say it's Bob. Suppose we let Charlie's locktime be identical to Bob's. And for maximal pessimism let's say Alice and Charlie collude. Here, Charlie could refuse to pass his signature to Bob and attempt to reclaim his coin at the exact moment of the timeout, while spending Bob's (depending on the exact permutation of spends, but at least, it's possible). Even though Alice didn't back out at her timeout in this scenario, which is weird, clearly this scenario is not safe for Bob, he has passed across a signature to Charlie with no time based defence against him.

These considerations make it obvious, I think, that the obviously sound way to do it is to stagger the locktime values according to the order in which signatures, and therefore secrets, are revealed. If the order of signature transfers is: first Alice, then Bob, then Charlie, then the locktimes on the backouts which pay each must obey L_A < L_B < L_C.

So I believe this ordering must be settled on in Phase 1 (because we define these locktimes before signing the backout transactions).

Generalisation from 3-3 to N-N

I believe this is trivial, modulo practicality.

Practical considerations, applications

The scenario described is a multiparty coinswap in which essentially a group of N parties could randomly shuffle ownership of their coins. This could be done with or without a coordinator (either Joinmarket style or server style), could possibly be done with a Coinshuffle++ type coordination mechanism and/or blinding.

Practicality: the biggest limitation is that of CoinSwap generally, but extended further: using staggered locktime backouts means that in cases of failure, participants may have to wait a long time for coin recovery. This gets linearly worse with anonymity set, which is not good. Would love to find a trick to avoid that.

On the positive side, there could be a tremendous boon over the 2-party case in that it's possible here to have a group of anonymous participants shuffle the history of their coins without any of the parties knowing the others' linkages.

Also positively, such larger group swaps may offer much larger privacy improvements in a very economical way (a few hundred bytes on chain per participant vs tens or hundreds of kilobytes via coinjoin? complete finger in the air here of course).

Other applications: leaving this open. Perhaps using adaptor signatures in groups like this (exploiting the linearity of adaptor signatures) has applications to second layer tech like Lightning or similar contracting.

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