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
- Use IP address instead of creating a new nodeId concept
- use the receipt of a new block as the expiration of the patience timer. I apologize for brushing this off before.
- 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.
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.
God approves this message. Protect yourself David, stay safe out there
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! (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.
What do we need to do to get GrinJoin as a standard feature in major wallets? How can people help make this happen?
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!
@shush thanks for sharing, I’ve been thinking along the same lines myself, but am not knowledgeable enough. One of the problems I’ve encountered, is that by sharing private keys (or “ways to unblind”) with other participants, these participants would be able to also decrypt the original message (the unaggregated transaction), wouldn’t they?
In my thinking so far, I’ve seen a lot of similarities between this problem and the Mental Poker problem, and the various decentralised shuffling protocols that’s come out of this, where an output/kernel would be the equivalent of a card to be shuffled. A big difference being that the exact deck of cards is not known to the participants in advance.
Virtue poker’s description of how they do the shuffle at the poker table seems relevant and interesting here.
Ignoring the DoS risk, tx validation, and other separate problems, if the main objective is to join inputs, outputs, and kernels in a way where the central party cannot trace the unjoined transaction back to a particular user, imagine a protocol where:
Each input, output, and kernel, are equivalent to cards in three distinct decks (blue, red, green cardbacks), and a “player” is a user, and the GrinJoin server is the “dealer”.
Each player first encrypts their own transaction(s) accordingly, hiding the true value of each card, and is equivalent of putting a “lock” on the cards.
There is a protocol where players share the encrypted cards with each other, each player put its own locks on all of the cards, and shuffle them. At the end of this, nobody will know the true order of the deck.
The GrinJoin server receives all the cards, does a shuffle, and puts their own lock on the cards.
Similar to 3, the cards are now shared sequentially amongst the players, but now the players remove their own individual locks. Still, the last player receiving the cafrds cannot see their face value, as they still have the lock of the GrinJoin server.
Finally, the last player sends the cards to the GrinJoin server, who can remove its own final lock and now has a verifiably shuffled deck without knowing which input/ouput/kernel are associated.
I don’t know if any of this makes sense, and it’s probably needlessly complicated. But each player would only need to trust themselves to shuffle the deck correctly in order for the outputs to be mixed.