Request for Funding @scilio (CoinSwap Implementation)

@scilio Any updates?
If so, you can pots an update here or give an update in the Grin CC meeting today at 12:00 today CEST, if your are available:

I’m truly sorry to have disappeared without giving notice. I’ve been dealing with personal issues that have consumed much of my time.

I have made good progress on this task, though. It was identified by phyro that my initial API allowed collusion between the initial and final nodes. I went back to the drawing board and came up with a new API.

The current draft of the API now just requires

  • ephemeral_key: secp::PublicKey
  • hmac: hmac::Hmac<Sha512>
  • commitment: secp::Commitment
  • payloads: Vec<EncPayload>

where EncPayload is a byte array that, once decrypted, contains the excess and either the routing_info for the next node or the rangeproof if the payload is for the final node.

After each hop, the current node will unwrap each payload, transform the commitment, ephemeral_key, and hmac, then forward the remaining payloads onto the next node.

I actually had to code this new API and the onion encryption components to convince myself that it worked. So I do have some working code that is nearly ready to share. It’s the language I had the least experience with, but since the community consensus was that Rust would be the easiest to support, that’s what I chose to use.

I’ll write up the API more formally and clean up the code this week. As soon as it’s ready, I’ll share links to everything here. Once again, I’m truly sorry for the lack of communication. I’ll do better.

13 Likes

Thanks for sharing a detailed update @scilio, shared this post in today’s Community Council meeting.

2 Likes

That’s not the onion encryption that the design calls for.
The payload for node i should be encrypted so only node i can decrypt it, which should result in the data for node i + the payload for node i+1.

With your vector of payloads, the first and last nodes could collude to correlate their data.

3 Likes

Given 3 nodes n1, n2, and n3, each with known pubkeys n1.K = n1.k*G, n2.K = n2.k*g, and n3.K = n3.k*G, the caller provides

* ephemeral_key: The initial ephemeral pubkey, R1
* commitment: The real input commitment C0
* payloads:
    1. E1(p1)
    2. E1(E2(p2))
    3. E1(E2(E3(p3)))

n1 then computes shared secret s1 = ECDH(n1.k, R1). Using s1, the node decrypts the 3 payloads to get p1, E2(p2), and E2(E3(p3)). It reads the excess x1 from p1.


n1 then calls n2 with

* ephemeral_key: R2 = BLIND(s1, R1)
* commitment: C1 = C0 + x1*G
* payloads:
    1. E2(p2)
    2. E2(E3(p3))

n2 computes shared secret s2 = ECDH(n2.k, R2). Using s2, it decrypts the 2 payloads to get p2 and E3(p2). It reads the excess x2 from p2.


n2 then calls n3 with

* ephemeral_key: R3 = BLIND(s2, R2)
* commitment: C2 = C1 + x2*G
* payloads:
    1. E3(p3)

n3 computes shared secret s3 = ECDH(n3.k, R3). Using s3, it decrypts the remaining payload to get p3. It reads the excess x3 and rangeproof Π.

n3 computes the final commitment as C3 = C2 + x3*G and verifies the rangeproof Π.

This can be seen in action in this test I wrote.

1 Like

It seems like you have n*(n+1)/2 decryptions in total which is of order n^2 instead of exactly n. Couldn’t n1 decrypt only the 3rd option and get p1 along with the next encrypted message? The encrypted payload would need a recursive form:

Payload {
  rangeproof: BP | None
  private_excess_share: x_i
  encrypted_data: Payload | None
}

It doesn’t actually involve more decryption. It’s a stream cipher, so whether we perform the decryption on the whole chunk at once, or decrypt each payload individually, the same amount of processing is required. You can think of the payloads as being one contiguous block of data instead of separate blocks in a list, and you’ll see that, in practice, it’s exactly the same as what you’re proposing.

btw, I chose to model it from the onion routing standard for lightning.

2 Likes

The commitment should not be separate, but there should be one in every payload, so the node knows which excess to apply to which commitment. This looks like a major oversight.

Ok, so that is essentially equivalent to using the intended

E1(p1 | E2( p2 | E3(p3)))

The excess is in each payload. Why does the commitment need to be there also?

Under data provision of your design, the inner nodes j ∈ {2...n-1} are to be provided with

  • commitment Ci,j-1
  • excess share xi,j

Since Ci,j-1 is actually calculated by node j-1, I don’t understand why we would need for it to be part of the encrypted payload.

1 Like

Because, as the proposal states:

Each node receives a sorted column, not knowing the i indices shown,
transforms each commitment by some excess specified for that commitment,
sorts the results, and passes on the new column to the next node.

To prevent correlations, node j must not know which commitment belongs to which user. That’s why the payloads are permuted by each node.

It’s a little worrying that you missed the essence of the design:-(

If there’s any aspect of the coinswap protocol that’s not entirely clear to you, then please ask for clarification, so we don’t have such misunderstandings.

Node j still won’t. For each i, a Ci,j-1 is computed by node j-1. The tuples (Ci,j-1, payloadsi,j) are then sorted by commitment (Ci,j-1), and the sorted matrix of tuples is then sent to node j. Node j+1 wouldn’t see Ci,j-1.

The design is clear to me. I believe we’re just speaking on different wavelengths :smirk:. I’ll finish writing the RPC layer and then take a break to more formally document the flow of data. That should clear up any misunderstandings.

7 Likes

I’m sorry for mistaking your deviation from the proposal as a misunderstanding. I now see that it’s a useful optimization.
My apologies, and good job on spotting the redundancy!

14 Likes

Milestone 1 is just about complete. I just have a bit of error handling left and some documentation to write. If someone could create a mwixnet repo in the mimblewimble github org, I’ll be able to create a pull request for everyone to review.

12 Likes

Repository created GitHub - mimblewimble/mwixnet: Implementation of the Mimblewimble CoinSwap proposal.

6 Likes

Thank you. I’ve created the pull request.

6 Likes

I think we need to come up now with a review process in order to accept the first PR.
Great work and now we need a community effort to review the PR.

Who would be able to review it?
@tromp @joltz @davidtavarez

3 Likes

I will do my best to give it a review this week.

First I need to familiarize myself with the protocol we are trying to implement. Is Mimblewimble CoinSwap proposal the completed specification or is there an updated one somewhere else?

7 Likes

The code is based on that design, with some modifications documented in the README

7 Likes

@scilio could you give an update on the 18th Agenda: Community Council (CC), 18 January 2022 · Issue #33 · grincc/agenda · GitHub . If you’re unable to attend could you leave an update on the forum?

1 Like

Milestone 2 is nearing completion. So far, it

  • communicates with a GRIN node’s API using jsonrpc calls
  • validates input signatures using the new Commitment Signature scheme
  • verifies input commitments are in the UTXO set
  • executes round every DAY_HEIGHT (1440) blocks
  • verifies generated output commitments are not in the UTXO set
  • builds the kernel and assembles the transaction
  • submits the transaction to the node

For milestone 2, I still need to

  • add reorg support
  • improve fee handling & wallet support (could fall under milestone 3)
  • add better e2e tests

Trying to add support for handling reorgs efficiently has been the main challenge so far. I’m getting frustrated by the lack of progress, so may skip this and come back to it after the rest of milestone 2 is finished and merged.

My original time estimates were apparently too optimistic. Estimating software is hard. But don’t worry, I’m not going anywhere. I’ll try to give more frequent updates so everyone knows I’m still here.

20 Likes