The yellow road

I know not everyone will agree the path described below is a good one. This is why, I’d like to invite you to share your view as well. Let me know if I made any mistakes.

My current view of Grin

There’s a lot of things that have been researched and are a possible path for Grin. I believe there are many things we can do that would make Grin better than it is today. The document shows a summary of things that I personally think would make the most yellow path for Grin.

Below are sections with changes I’d hope come to life at some point.



The current IBD process in Grin is very inefficient. PIBD allows for a faster, more efficient and less error prone sync for new nodes.
It would also allow us to eventually get rid of the large utxo hashset zip files which are required for the current sync process.


A new node needs to download:

  1. All the kernels
  2. The UTXO set

With IVC, we might be able to show a short proof that would allow us to skip 1. entirely - the validation of all past kernels would be instant. This would mean we’d no longer be able to seed new nodes except if they were ok with an IVC proof. The reason they might not be ok is because IVC is a bit more complex and people might prefer simpler methods of verification like linearly verifying kernel signatures as we do today.

Pruning node

We can prune everything away and still be able to fully validate a new block. We can achieve the Utreexo-like constant node without introducing a new accumulator. More on how to do this can be read here.


CoinSwap proposal

I hope the coinswap proposal gets implemented and is used by default in the popular wallets. This is already a good progress compared to existing mixing services on Bitcoin. Eventually, people will figure out designs with even better properties, but this is already quite good.

Payjoins (reducing the UTXO set size)

Let’s color the outputs that came from the coinswap service with a yellow color and those that were created in a regular transaction with black color. If all of our created outputs go to the coinswap service, then we have plenty of yellow outputs available.

If the receiver contributes a yellow output as an input to make a payjoin transaction, this means that the payjoin no longer leaks an input from the receiver because even if they contributed that input, that output is yellow which means that it’s just one of N inputs that were in that coinswap transaction. So if the coinswap service produces a transaction with 100 outputs, then payjoins come at negligible privacy cost which means they can be used in every transaction as long as we have yellow outputs available. We could then make transactions default to payjoin transactions in case yellow outputs are available.

The reason we might want to make payjoins by default is to avoid increasing the UTXO set. This should make the chain significantly smaller in the long run because an average transaction no longer increases the UTXO set by 1.

NOTE: Transactions where you contribute yellow inputs would get a very good protection against replay attacks. It’s not a perfect protection, but it makes it magnitudes harder to pull it off as described here.

Transaction building

Embracing interactivity

In my opinion, we’ve made a mistake allowing auto-signing of transactions. The signature is an action that has a meaning and it should never be done automatically on behalf of the user - unless we could automatically check that we’re signing exactly what we expected. Doing auto-signing introduces a couple of issues:

  1. Disjointed flows - The invoice flow (RSR) has step2 interactive while the payment flow (SRS) does not.
  2. Play attacks - These attacks take advantage of not understanding that the signing is taking place. The attack exploits the fact that a party that completed only 2 steps thinks they’re safe from getting their money taken away. This comes due to the fact that they don’t understand they already put their signature on the transaction. In my opinion, hiding the signatures from the users is a terrible idea as it makes it counter-intuitive to understand the attack or transaction cancellation process.
  3. Doesn’t allow for more complex payment proofs - There’s no way to check the memo as a receiver today.
  4. Tries to inhibit the interactive nature of MW - It doesn’t take advantage of either interactive or noninteractive transactions.

Manually confirming transactions comes at a great benefit because the flow is the same for any transaction:

  1. Every interaction is asynchronous
  2. Party A: Send transaction offer along with payment_info (payment proof) to B
  3. Party B: Check contract+payment_info, add outputs and sign if everything looks good
  4. Party A: Add outputs + auto-sign (this signature can be automated because it’s expectation can be auto-checked from slate1)

These steps are the same regardless of:

  1. The flow (SRS/RSR)
  2. The transaction type (normal/payjoin)
  3. What kind of fees they want (they could pick custom fees or take the default)
  4. Whether the parties have auto-adding of outputs or manual-selection
  5. Whether the transaction has a more powerful payment proof with a memo or a simple one
  6. Whether we’re using a software or a hardware wallet - hardware wallet requires confirmation so by having the flow asynchronous we enabled people to use hardware wallets

I think this is a big simplification because things get unified. On top of that, we solve these:

  1. Awareness of signing - play attacks become way more obvious and easier to explain. Safe-cancel actually makes sense.
  2. We get complete control of the wallet state since nobody can force outputs to your wallet. A feature only possible in Mimblewimble design.
  3. (perhaps) Hardware wallet - a hardware wallet requires you to confirm what you sign. If you’re using a hardware wallet for Grin, you’ll likely have to confirm what you’re signing as well which means that the flow for the sender and the receiver with a hardware wallet might be unified.
  4. Layer 2 similarity - Lightning wallets have interactive transactions with confirmation which is another unification.

One-time addresses

This seems like a good idea, but it could introduce problems for payment proofs if we’re not careful. What we today consider being the identity is the Grin address which is static. Identities have to be static in order to not be “ephemeral” and useless. If we only bolt on one-time addresses without introducing a new identity element, then payment proofs only prove how much was paid. They no longer prove who paid whom because it’s a one-time identity and hence just a random string of characters. This can probably be solved, but it’s something we should be careful about as we don’t want to solve one thing to introduce another thing that needs solving.

Attack protection

Replay attacks

We’ve mentioned the play attacks above. The replay attacks would also need to be resolved. There were many ideas mentioned, but we didn’t find a solution we all agreed on. Hopefully someone comes up with a new idea that we all consider good.



We’d have to figure out the best way for exchanges to integrate. This would likely mean copy pasting slatepacks. There’s no reason to use Tor when you already have a communication method that provably works which in this case is the exchange’s website. If you can use the exchange, then you can also paste slatepacks there. The most important part is to figure out how they can integrate in a reliable and secure way.

Atomic swaps

This is almost finished afaik, but it needs to be reviewed. Unfortunately, we seem to be currently lacking people having the knowledge and time to review this, but hopefully we get more people that are able to push this to the finish line soon enough.

Hardware wallet

This would be great to have so hopefully Mark Hollis continues on this. As already mentioned above, a hardware wallet requires the sender to confirm the transaction before it goes out. Since Grin requires producing a signature also from the receiver, the receiver with a ledger wallet would also need to interactively confirm it.


It is a pity that I do not know programming

1 Like

Thank you for sharing. I would add that we also need to focus on write tools to build on top of Grin. Unifying the APIs across both implementations (C++ and Rust) could be a first step. This will help people to implement whatever they want on a standardized manner.