Request for Funding @scilio (CoinSwap Implementation)

since @scilio did not provide any references of his capabilities and past work done and is also completely unknown to the community a cautious approach regarding the request is advisable.

I agree. Both Points address the main concerns on both sides (unknown dev vs. whoever pays him) effectively:

Nr. 1. Cutting workloads into chunks would mitigate some of the risks on @scilios side. Imagine working 2 months straight on Grin code, turning everything in and being destroyed by Tromp because the code is deemed as “too complicated” and as a violation of the sacred minimization-principle.

Smaller milestones can avoid these potential problems.

Nr. 2: This would mitigate most of the risks regarding the development funds that are inherent when funding unknown devs.
In a typical work environment, the client/employer pays its employee in advance. However, he does so typically because he believes that the employee is up to the task. Such proof is typically done via resumes, job references, presentation of completed projects and so on.

@scilio is well aware of this fact which is indicated that he proposed by himself that he will do the work first and get paid later.
So i see it that we just need to define the concrete “chunks”/milestones, timeframes (which must not be too long, see Nr.1) and payment and we should be good to go.

4 Likes

Haha, stomp by Tromp :))

More seriously though, one of the really nice things of the coinswap proposal is that its design is incredibly simple. I would hope this also translates in the code because it makes it:

  1. easier to review
  2. more likely to spot mistakes
  3. easier for anyone else to contribute to the code or continue where the project left off
1 Like

Regarding the reviewing, I think both @oryhp and @davidtavarez would be good candidates for reviewing, as long as they can read the code…
In the proposal it states there are libraries in Rust, C++ and GO. Unless we have people here who are used to GO, I think we should discard this option since even if we would have good code, no one here might be able to properly review or continue the project except @scilio

I would prefer seeing this implemented in go than in c++ since go is much simpler from what I’ve heard so it should be easier to verify the code and it’s probably easier to get go devs nowadays than c++ ones

1 Like

That is true, actually there are more GO devs than Rust Devs in general while GO has better memory safety than C++, although somewhat weaker than Rust.
Still we would need people who can review the code for now to work with @scilio, are there any Golang programmers in the community?

Pretty sure Quentin knows Go. I’d most welcome an implementation in rust that would add a function that creates a 1-1 self-spend to a rust tx package which could be reused when wallets implement this. We’d need this for tests anyway.

1 Like

What I like about C++ is that you can easily compile the code to a bunch of platform, as we are doing with Grin++, you can run Grin++ on Android, Pi4, Linux, Windows and macOS; I don’t how to achieve that using Go or Rust, but I don’t think is that easy as it is with C++.

As long as @scilio includes Tests, like he/she said which is perfect, we’re good. A tests coverage of 90% should be good. With a unit testing mindset at the moment of writing the code, the functions and methods can be audit independently and anyone could perform a Fuzz testing.

I suspect both Rust and Go are good at this as well Cross Compiling Rust for the Raspberry Pi unless you had something specific in mind.

I don’t know whether you need any other things though.

I’m speaking on my behalf. I tried a few times to generate a binary of grin (the Rust implementation) for Android and arm64 without success :sweat_smile:

1 Like

I have had no problem compiling grin and grin-wallet on rpi 32-bit and 64-bit OS. Testing grin++ right now.

@scilio are you still interested in taking this on? I would love to see you start working on this.

10 Likes

Absolutely. I’m not able to make dramatic alterations to the payout schedule. I need to be able to pay bills.

I figure the best path forward would be to provide a fully documented API for review to alleviate some of the concerns about skills or knowledge. I’ll have more to share soon.

23 Likes

The first version of the external API is now available for review.

The external APIs are defined using OpenRPC. Simply copy the contents of openrpc.json into the OpenRPC Playground to explore the APIs.

11 Likes

The commitment signature of the message “MWIXNET”,

It may be wise to have the message additionally commit to the date of the coinswap (and for an hourly swap service, the hour of day as well).

           "description": "The excess scalar encrypted using label \"excess\" ",

Why does this field need to be separately encrypted? And what does encryption using a label mean?

           "description": "The range proof encrypted using label \"rangeproof\" (only required for the final round)",

Since the rangeproof is only required for the final node, I don’t think it belongs in the per-round data.

Does the json array type for rounds make sense when its elements will be at different nesting levels in the onion encryption?

2 Likes

Excellent suggestion. I will add those fields to the request and to the signature.

Separately from what? There’s not an actual onion-layered bundle. The only encryption used is on the excess, and for the rangeproof on the final node. Also, the wallet will communicate with Node 1 using tor, so that will use tor’s encryption, of course.

As I describe this, I realize it doesn’t make sense to use onion addresses for the node_address field, since the communication between MWixnet nodes may not even be over tor. A simple x25519 pubkey would be sufficient.

It’s just a salt is all. The wallet generates an ephemeral keypair for each node, uses the private key and the node’s x25519 pubkey to perform diffie hellman, calculating shared secret k. From there, the wallet generates an encryption key E_1 for the excess by computing E_1 = hkdf(key: k, salt: "excess"). For the final node, we also generate the encryption key E_2 for the rangeproof by computing E_2 = hkdf(key: k, salt: "rangeproof").

I considered this, but I thought it much cleaner to keep the enc_rangeproof in the same structure that held the public keys. Doing that makes the API very uniform, with 1 array entry per MWixnet node.

Can you elaborate on this? My remark about not rolling our own onion layered encryption might make this question obsolete, but it’s possible I’m misunderstanding.

2 Likes

In my attempt to simplify the encryption scheme by removing the onion layer encryption, I overlooked the important fact that node 1 and node N could just collude to link the original commitment and new rangeproof :slight_smile: . Thank you @phyro for finding that weakness.

Please give me a few days to add onion layer encryption back to the API.

4 Likes

Do we know if ComSig Signature for Mimblewimble Non-Interactive Transaction is secure? It’s very important we use a secure way of proving ownership as this could itself leak information that would allow stealing of coins.
Perhaps a much simpler proof of ownership would be to show a BP for C' = C + C.
Not sure if it is simpler, but using BPs for ownership proofs doesn’t add any new scheme and perhaps saves some scheme implementation headache/auditing.
This might even make the onioned message simpler e.g.

M {
  // The first and last node receive a rangeproof.
  // The first for ownership proof, the last for the final output.
  Rangeproof: BP | nil
  // Partial excess
  ExcessShare: Scalar
  // M' is the message for the next node. Nil if last node.
  M': M | nil  
}
where you receive a pair <Enc(M, your_key.pub), Enc(C)>.

Every a mwixnet node receives an encrypted commitment and an encrypted message. The message is encrypted by the coinswap owner while the commitment is encrypted by the previous node. In the case of the first node, it is encrypted by the coinswap owner. So a coinswap submitted by the user to node1 is a pair <Enc(M, node1.pub), Enc(C, node1.pub)> where C is a valid input in the UTXO set. With this structure, node at position i decrypts the commitment it received from the previous node, decrypts the message and adds the scalar*G to the commitment. Then it encrypts this new commitment for the next node and sends it along with M'. Only the first node will need to carry the rangeproof that serves as the proof of ownership because it is only in the very first message.
There are probably simpler ways of doing this, but it might be worth thinking in this direction as well.

1 Like

It is honest verifier zero knowledge in the same way that Schnorr sigs are. A simulator can pick e, u, v at random and produce a valid transcript with R = u*G+v*H-e*C.

Interestingly, a regular Schnorr signature is a Commitment signature with v=0.

Clearly, (generalized) Schnorr sigs are WAY simpler than bulletproofs. What you mean is “more commonly used” rather than “simpler”. BPs are also an order of magnitude larger, although that has a much smaller impact on the entire coinswap submission which already contains a BP along with many other data items.

I say we go with the simpler and more efficient commitment proof of knowledge and get someone like Andrew Poelstra to bless it.

2 Likes

Separate from the onion encryption.

Why not? That’s what the coinswap design calls for.
The only reason anything need encryption is so that one mixnode cannot see the data for another mixnode.

I think it’s much cleaner to reflect the special roles of node 1 and the final node.

Don’t you already separate the proof of knowledge that’s particular to node 1?

We’d not be rolling our own but just replicating what TOR does.

4 Likes

@scilio any update on this?

2 Likes