Non-Interactive Transaction and Stealth Address

Hi there! I’m work on an interesting feature for mwc, here is a draft RFC style document but would like to collect your good proposals both on NIT(Non-Interactive Transaction) and on SA(Stealth Address) instead of comments only :slight_smile:

The working will submit to that PR from time to time, so the document itself could subject to changes frequently.

(and happy we have forum now, I’m glad to be the first post here :rocket: hope to see more and more posts in mwc forum~)


A bit updating on the “Drawbacks”:


Shortly, as described in §2.2.1 of NIT paper, the cut-through in same block and in transaction pool (i.e. mempool) is frozen for NITs. The cut-through across the blocks is still feasible, which is great to reduce weight for non-archive nodes.

In detail:

  1. The fundamental difference from Bitcoin or any other Non-MW blockchain still keeps here, the MWC blockchain still can shrink over time. No changes here for NIT. Technically speaking, this is done by cut-through across blocks.

  2. Theoretically, the cut-through in “same block”/“transaction pool” is also helpful for transaction graph obscuring. But practically, because this ONLY works for the kind of 0-Confirmation Transaction, it does not make a lot of sense in reality. In most of cases, zeroconf transactions are completely insecure in blockchain because of double-spend possibility.

  3. For NIT, there’s another insecure case for zeroconf NIT besides the double-spend, the dishonest receiver could use it to deny the receiving. So we just freeze this (cut-through in “same block”/“transaction pool”), but I don’t think this freezing is a real “drawback” in any sense.


Rollout/Deployment (HF2) Plan (Draft, TBD)

This will be updated as there is progress, with a statement in the comments section each time there’s a significant change.

Important Block Heights and Dates

Event Date or Block
Testnet Hard Fork Block Height 833,450
Testnet Hard Fork Date (expected) 2021-06-15
Hard Fork Block Height 919,850
Hard Fork Date (expected) 2021-08-15 (est.)

Important Information:

  • MWC v6.0.0 is a network wide upgrade. Apart from updating their binaries in order to use MWC after the upgrade, users are not required to do anything. Stored MWC coins will not be affected. Beware of scams telling you to move your coins elsewhere.
  • Even it’s designed with completely backward compatibility, all wallet users are strongly proposed to upgrade their wallet software to the latest release.


Date Milestone Description
2021-05-15 Beta Binaries Release Release of mwc-node, mwc-wallet beta binaries.
2021-06-15 Testnet upgrade Launch of testnet hard fork and public testing. Release of mwc-qt-wallet beta binary.
2021-07-15 Release candidate binaries Release of mwc-node, mwc-wallet and mwc-qt-wallet RC binaries.
2021-08-05 Final release Release of mwc-node, mwc-wallet and mwc-qt-wallet binaries.
2021-08-15 (est) Mainnet upgrade MWC is forking to v6.0.0.

Note: Actual dates (but not the hard fork block height) may vary slightly based on the current circumstances.


The node implementation is coming to the final stage: the tests part. During the unit tests, I found the balance equation (2) has problem when we use mixing mode (i.e. both Interactive Transaction and Non-Interactive Transaction scheme are supported in MWC).

The Problem Description

As in paper page 4, in balance equation (2):
Pi’ + (E’+s*G) = Rc + Ro
in a typical single input double outputs transaction. But the problem is, in case a mixing scheme, it’s possible to have none Rc and/or Ro in the whole block. Since the balance equation (2) share the same E’ and total offset with balance equation (1):
(xi*G+ai*H) + (E’+s*G) = (xc*G+ac*H) + (q*G+ar*H)
There’s a possibility to have nothing of R to make this equation (2) balance.

The Solution of the Fix

Obviously this problem only exist in a mixing scheme. And an easy and reasonable solution to fix this problem is to define a new consensus for coinbase output:

All coinbase outputs will use NIT style output format, i.e. a R and a P’ are attached.

With this “fix”, the cost is the coinbase output payload size increasing a little bit. But an interesting benefit of this change is, the mining node will never need an online wallet running and connected! :sunny:

Hope to hear the comments from you about this change :sunflower: and in the same time I will try making test code on this change.


I like this idea. It is really pain to have the wallet be always online for the mining.

Am I understand correctly that with this change, the stratum config will need stealth address instead of miner’s wallet connection. So instead of ‘wallet_listener_url’ we will have something like “mining_reward_address” ?


Yes, exactly. only ‘mining_reward_address’ is needed.


The NIT coinbase reward has been implemented in git commit:

But I just found that I made a mistake on the root cause of problem described above (i.e. equation (2) balance problem in the mixing scheme), after several days of struggling to fix the block validation failure on tests.

Problem (Re-)Analysis

Let’s say there are 1 traditional interactive transaction T1 and 1 non-interactive transaction T2:

T1 : I1 + (E’1 + s1*G) = O1+O2

T2 : I2 + (E’2 + s2*G) = O3+O4
        P’2 + (E’2 + s2*G) = R3+R4

Now, let’s have a look at what will happen in the CoinJoin for T1 and T2:

T1,2: I1+I2 + (E’1+E’2 + s1,2*G) = O1+O2+O3+O4                 ---- (1)
          P’2 + (E’2 + s2*G) = R3+R4                                                       ---- (2)

where, s1,2 = s1 + s2, remember that each transaction data structure has only 1 Offset element.

Then, we have 2 problems here:

  1. We don’t have a method to differentiate the E’2 from E’1, so the validation of equation (2) can not be executed.
  2. The validator can only see s1,2, the merged offset. There’s no way to get s2 anymore. This also makes the validation of equation (2) can not be executed.

To fix the problem 1, we could extend the KernelFeatures definition to define more enum variants, so as to differentiate the non-interactive transaction kernel.

To fix the problem 2, looks like we don’t have choice other than adding a new offset in the transaction data structure, this new offset will only be used by non-interactive transaction. And a corresponding new Total Offset is also needed in the block header.

Currently, I’m thinking the possible side effects of these fix solution, and at the same time, welcome any comments on this proposal :sunflower:

1 Like

Am I understand correctly that you need two independent offsets and excess? May be it make sense to have two kernels for mixed transactions. Transaction allows to have multiple kernels.

I mean there need 2 independent offsets but single excess in one NIT transaction.

In the merged transaction T1,2, there must be 2 kernels.

Or maybe you’re talking about the two kernels in one single NIT transaction? You make me think an idea of a naive solution: giving 1 excess/kernel + 1 offset for each equation (1 and 2), that could be a very raw design and need one more kernel payload size, and it can not make the bad differentiation better.

Indeed (as discussed in Discord), I also don’t like the kernel differentiation (between IT and NIT), I have been thinking of that in these days, trying to find a better solution…

Yes, I am thinking about 2 kernels in a single mixed NIT + IT transaction. It is a naive solution, but normally we shouldn’t have Mixed transactions (mixed are fine for transition period. I can expect that after some time period most outputs will be NIT outputs).

The kernel differentiation is bad, but can we make them the same? Making them the same will be really great. But also we can think that mixed transactions will exist limited time on the blockchain. In this case it is not a big deal.

I think I got an idea to solve the problem :slight_smile: use “virtual equation (2)” for Interactive Transaction.

T1 : I1 + (E’1 + s1*G) = O1+O2
        I1 + (E’1 + s1*G) = O1+O2                 ---- (virtual eq2)

T2 : I2 + (E’2 + s2*G) = O3+O4
        P’2 + (E’2 + s2*G) = R3+R4

For CoinJoin of T1 and T2:

T1,2: I1+I2 + (E’1+E’2 + s1,2*G) = O1+O2+O3+O4                 ---- (1)
          I1+P’2 + (E’1+E’2 + s1,2*G) = O1+O2+R3+R4                 ---- (2) including virtual ones.

We can give a virtual view on Interactive Transaction (here is T1 for example), to pretend there’s a virtual equation (2) there, with a virtual P’1 = I1, and a virtual R1 = O1, a virtual R2 = O2.

Then we don’t need differentiate both kernels, and don’t need an independent new offset.

1 Like

I don’t have the knowledge to confirm if this solution will work, but if it do, I think I see the benefits. IT and NIT have two distinct transaction kernels, so it would be possible to identify NIT from IT transactions and this is not good for privacy. This proposed solution, virtual equation, will obfuscate the use of NIT from IT as both kernels will look the same, keeping privacy while MWC keep both support for NIT and IT.

Sounds great. Am I understand correctly that excess instead of ‘random’ number will be a result of equation.
The transaction offset (Blinding factor) will work the same way as we have it how.

Update: This “fixing” had a major mistake on the missing fee part so it doesn’t work at all. Let’s wait a new fix on it.