Non-interactive transactions

Grin transactions are interactive because without input of the receiver there is no way to make sure that the sender cannot spend the coins, i.e. we need to delink the sender from the commit.

But this does not have to be done by the receiver. First let us look at a simple case where Alice wants to send funds to Bob and Carol is online to delink Alice from the transaction output. In addition Alice, Bob and Carol have all published a public key P and posses the corresponding private key x:
P_i = x_i * U
where U is a curvepoint that is different from the two points (L,G) used in the Pedersen commits
C = vL + sG
Note that I often will use P_i as a number and not as a curvepoint. Equations below should be understood accordingly.

From these public keys shared secrets between all parties can be established.
s_ij = x_iP_j = x_jP_i
and these can be used as blinding factors in the transaction. Alice will set up the commit
C = v*L + s_AB * G + s_BC * G
and this commit can be signed by aggregating signatures from Alice and Carrol. It can be spent by Bob; or when Alice and Carrol collaborate.

This is already somewhat better than putting the money in a channel where both Alice and Bob can spent, but not really satisfactory as Bob needs to trust Carrol.
But there is no reason why only one person beyond Alice should be involved. If we build a system where anyone can add information to delink Alice this would be secure as long as only one of the signers is honest.

This would be set up like this:

  1. Alice provides an initial commit
    C = v *L + s_AB * G and a Hash H©
  2. Other participants can now add to this commit by sending a public key P_i and signing the Hash H to (U,P_i) proving they know x_i.
  3. These then commit I_i = x_i * G (which is not P_i = x_i *U!). The same signature above verifies that x_i is the same as for the public key as the signature also signs H to (G, I_i)
  4. Alice adds to the commit C
    C += P_B * I_i = s_Bi * G
  5. After some while Alice finalises C and asks all participants for a valid signature to the transaction, and aggregates them. If it does not validate the people that did not sign correctly are dropped and step 5 is repeated without them.
  6. Alice pushes the signed transaction to the chain and gives Bob P = Sum(P_i) and this allows Bob to spent the output.

For Alice to spent the output all people involved in delinking her need to cooperate. The delinkers can never spent without Alice even when they cooperate. While this is not 100% safe only one honest participant already guarantees safety. The idea is decentralised and should be better than having a single trusted third party. For smaller amounts this should be secure enough. Plus it is easy to find public keys for anyone that has a BTC address from which there was a transaction. Then girn could be sent non-interactive directly to a BTC address, just giving people in BTC some grin to play with it if they want.

Are there any problems I am missing?

If Bob didn’t trust Alice, and Alice is the one doing all this work, how is this an improvement?

Alice finds a bunch of dishonest signers, Alice asks them to join signing service, Alice repeatedly sends transactions to the service until she gets one made with only dishonest signers(possibly reporting honest signers allong the way), having successfully created a dishonest transaction Alice then and only then does 4, 5 and 6

You are correct, Alice should not prepare the transaction (steps 4-5). She should only get the final aggregate where she can check that everything works out and Bob will be able to spend. Then she signs that and publishes in 6.

After all Alice wants to send the transaction to Bob, all the work is just to make sure that she cannot change her mind later and claim the money back.

I have thought a bit more about this and I think the idea can be improved by using zero-knowledge proofs.

Every user sets up a public key and has a corresponding private key P_i = x_i * G
Using these shared secrets can be found between all participants as s_ij = x_ix_jG = x_i *P_j = x_j * P_i

  1. Alice provides an initial commit to pay Bob
    C = v *L + s_AB * G
    and proves that s_AB is spendable by Bob via zero-knowledge proof. For this a bilinear e(A,B) over the elliptic curve is required as used in Zcash. The proof is that e(s_AB *G, G) = e(P_A, P_B). It only requires knowledge of the public key P_A.
  2. Other participants can now add to this commit by providing C_i = s_iB *G plus zero-knowledge proof that e(C_i,G) = e(P_i,P_B), requiring nothing but P_i
  3. Once enough people have contributed the transaction is finalised. The P_i are summed to P = Sum P_i and the commit to C + Sum_i C_i
  4. The commit is signed by Alice, verifying that the output is spendable by Bob given the accumulated public key. This later also provides a proof of payment if necessary.
  5. The commit is signed by all other participants
  6. The transaction is broadcasted

The idea still suffers from the problem that Alice may repeatedly create new payments until only dishonest verifiers are participating. To make that impossible Bob could set up a known list of Public_keys that are required to participate in the process.

Realistically these could be some central trusted signers and in addition random people could still join in to increase security. One honest signer is enough to make the process safe.