Yo Dawg, I heard you like CoinJoins

Then this proposal is to implement that feature :slight_smile:


I wonder what happens if central server goes down?


There will be a fallback mechanism to “fluff” the transaction if it isn’t seen in a certain amount of time.


I love this,
question - as grin gets bigger will we be able to further extend the service to something such as :
a) if a user wants to be put in front of the queue in the sense that they take priority over still awaiting transaction pool members (if u would call them that), then can we request a compulsory donation (haha).
b) that donation could go towards people who offer currency as stake for circulation or simply to users who wait the longest for their transactions (patient lizard ppl).

–please humour me / all g if u dont xD


@rodarmor When I first read that proposal, I misread it terribly, and so quickly brushed it off as deeply flawed. Upon re-reading, I realized what you were saying, and it’s actually very similar to what I was planning on doing anyway, with a few key improvements. The only changes I would suggest is we

  1. Use IP address instead of creating a new nodeId concept
  2. use the receipt of a new block as the expiration of the patience timer. I apologize for brushing this off before.
  3. Instead of just waiting for the tx to get to a fluff peer, which may never happen anyway due to cycles, just use probability as before, except instead of fluffing, make one additional hop to one of the fluff peers.
1 Like

No worries! I surely could have done a better job explaining it.

That’s a good idea. Two peers behind NAT or on the same box would get the same ID, but that’s probably not enough of an issue to introduce a separate node ID.

That seems reasonable, as long as a single block time gives adequate opportunities to aggregate transactions.

An alternative might be to immediately fluff a transaction if you are stemmed it twice. I.e. on first receipt of a stem transaction you stem it, but if you receive it again you’re probably in a cycle, so you fluff it. I don’t really have any reason to believe that this is better or worse than using probability though.


I announced in a few other places already, but https://grinscan.net/block/456188 contains the first ever “GrinJoined” transactions. 9 different transactions were sent via TOR to a GrinJoin server (grinjoin5pzzisnne3naxx4w2knwxsyamqmzfnzywnzdk7ra766u7vid.onion), and were joined together before ever being seen by the p2p network.


Very cool stuff.

Just 3 more in the pack, and we are already better than Monero coin! :smiley: (joke)

In all seriousness, thank you very much for your continued great work


Cool. How you think could GRIN introduce something similar with this approach? https://ethresear.ch/t/ethereum-9-send-erc20-privately-using-mimblewimble-and-zk-snarks/6217

Such approach uses MW and unlinks TXOs destroying the graph.

1 Like

What do we need to do to get GrinJoin as a standard feature in major wallets? How can people help make this happen?

1 Like

The upcoming Grin++ release (was supposed to be this weekend, but I’m delaying again) will be as simple as:

For all other wallets, the API is super simple. Just make a JSON-RPC request via TOR to grinjoin5pzzisnne3naxx4w2knwxsyamqmzfnzywnzdk7ra766u7vid.onion/v1 with a method of submit_tx and the params field simply needs to contain a field called tx which contains the JSON serialization of the transaction.


Sweet. Does the GrinJoin server see all transactions in their de-aggregated form?


Yes, but at least it’s not an unknown person running a sniffer node.


Yep. Scout’s honor I don’t do any logging. But since cryptocurrencies don’t usually rely on Scout’s Honor, better solutions are needed.


Does this GrinJoin option replace dandelion stem phase?


Yes, dandelion would actually result in less privacy, so we just skip it and use tor instead.


I wonder if it’s possible to blind the transactions before they are sent to the grinjoin server? Can we figure out a way to blind the transaction so that the grinjoin server doesn’t see which output is being spent? After aggregating the transactions, the blinding factors are shared between the join participants (not the grinjoin server), then each participant can derive the final joined transaction by removing all known blinding factors. Now each participant can broadcast the single join transaction to the network.

Another way of looking at this: A grinjoin server takes anonymous transactions and aggregates them into a blinded join transaction. The server then sends back the blinded-join-transaction to each anonymous participant. The participants then exchange with each other their secret blind factors to get the committable join transaction.

There would need to be a way for theses participants to communicate with each other anonymously as well. Possibly using Tor? The grinjoin server could include each participants supplied form of communication.

EDIT: Here’s what I’m thinking.

Step 1: Participant has a transaction they wish to commit anonymously to the blockchain. They create an asymmetric key pair. They use the private key as the blinding factor to create a blinded-transaction. They also use the private key to sign their communication-method. The communication-method could have different supported protocols for communication, but preferably it’s an onion address form which the participant can receive requests. The participant sends the blinded-transaction and the signed communication-method to the grinjoin server as a payload.

Step 2: The grinjoin server receives the payload and waits for more payloads. As the server receives more payloads, it joins the blinded-transactions together until a certain amount of joins which can either be specified as criteria in each payload or set to a standard default number (let’s call this max-join). Once the number of transactions reach the max-join, the server sends the blinded-join-transaction and each participant’s communication-method to each participant using their communication-method.

Step 3: A participant receives the blinded-join-transaction and a set of communication-methods. The participant then sends their private key (created in step 1) to each other participant using their communication-method.

Step 4: Concurrent to step 3, the participant receives private keys from each other participant. The participant must verify the private key using the signatures included in each communication-method. Once all private keys for each communication-method have been collected, the participant then removes each private key (blinding factor) from the blinded-join-transaction. The outcome is a join-transaction commitment ready to be submitted to the blockchain.

Note: This concept depends on the ability to add and remove blinding factors to join-transactions. This means blinding-factor arithmetic must be associative.


Nice work David! Does it run in a fixed interval or does it wait for a threshold?


Fixed interval. Leaning toward 10 minutes. Thresholds just open up the possibility of sybil-like attacks.


I sort of follow what you’re saying, but there are a few parts that aren’t entirely clear. First off, confirm for me what you mean by “blinded-transaction”? What are we blinding exactly - kernel? Inputs? Outputs? tx Offset?

If the transactions are blinded, do you have any way of validating them before unblinding? If not, how do you deal with the case where the final unblinded Join transaction is invalid? It doesn’t seem like there’d be any way to know which pre-joined transaction was invalid, so it’s easy to DoS.

I’ll have some follow-up questions based on your responses to those few questions. Thanks!