A high-level overview

© Tari Labs, 2018-2021. (License : CC BY-NC-SA 4.0)

Key features

  • No addresses
  • Completely private
  • Compact blockchain
© Tari Labs, 2018-2021. (License : CC BY-NC-SA 4.0)



© Tari Labs, 2018-2021. (License : CC BY-NC-SA 4.0)

Transactions explained

Notice no public addresses are used!

The recipient must be available to create a transaction, but he needn't be online at the time of the transaction.

Email, instant-messaging, wallet apps, or carrier pigeon are all valid means of the recipient sending his public key to Alice.

© Tari Labs, 2018-2021. (License : CC BY-NC-SA 4.0)

Basic transaction

Here's the basic transaction:

Inputs Outputs
3 2 1 f
Alice's UTXO To Bob Change fee

Assume the fee is zero for now; it doesn't change anything.

© Tari Labs, 2018-2021. (License : CC BY-NC-SA 4.0)

Now multiply both sides by the generator G on the EC:

3.G=2.G+1.G+f.G3.G = 2.G + 1.G + f.G

Since G is a constant, the math above still holds, so we can validate that Alice is not
stealing by checking that

(3.G)(2.G)(1.G)(f.G)0(3.G) - (2.G) - (1.G) - (f.G) \equiv 0

but note that we only see public keys and thus the values are hidden!


Note: Technically only scalar integer values are valid for elliptic curve multiplication. In practice,
we'll be using MinoTaris (name TBD) so that the amounts are always integers.
The transactions aren't sent as an equation like this, but as a list of inputs, outputs and the fee. The fee
is in cleartext, but you still need to blind it to check the maths.

© Tari Labs, 2018-2021. (License : CC BY-NC-SA 4.0)

But wait...

But if GG is constant and known (it is), couldn't someone just pre-calculate n.Gn.G
for all reasonable values of nn and scan the blockchain for those public keys?

Basically, YES!, so we're not done yet.

© Tari Labs, 2018-2021. (License : CC BY-NC-SA 4.0)

Blinding factors

We need to add randomness to each in/output to prevent a pre-image attack. The basic idea is to do this by adding a second private key to each output.

Input were given their private keys when they were outputs in a previous transaction.

So what if we rewrite the inputs and outputs as follows:

Cni=n.G+ki.HC_{ni} = n.G + k_i.H

where HH is a generator on another (specially selected) EC.

This completely blinds the in- and outputs so that no pre-image attack is possible.
(And is called a Pedersen commitment).

© Tari Labs, 2018-2021. (License : CC BY-NC-SA 4.0)

Alice now builds a transaction like this:

(3.G+k2.H)3T UTXO(2.G+k1.H)2T to Bob(1.G+k3.H)1T change=f.Gfee \underbrace{(3.G + k_2.H)}_{\text{3T UTXO}} - \underbrace{(2.G + k_1.H)}_{\text{2T to Bob}} - \underbrace{(1.G + k_3.H)}_{\text{1T change}} = \underbrace{f.G}_{\text{fee}}

Since in an honest transaction*

3.G2.G1.Gf.G=E=03.G - 2.G - 1.G - f.G = E = 0

this becomes

k2.Hk1.Hk3.H=E=0k_2.H - k_1.H - k_3.H = E = 0

* We'll examine the case where someone is cheating and E0E \ne 0 shortly.

© Tari Labs, 2018-2021. (License : CC BY-NC-SA 4.0)

and so we require

k2k1k3=0k1=k2k3 k_2 - k_1 - k_3 = 0 \\ \therefore k_1 = k_2 - k_3

Alice sends Bob this transaction information (T1) and lets Bob know that his private
key must be k1k_1. To prevent Alice from spending Bob's newly earned Tari, he
can choose a new blinding factor r1r_1 and rewrites the transaction as

(3.G+k2.H)(2.G+(k1r1).H)(1.G+k3.H)f.G=r1.H+E (3.G + k_2.H) - (2.G + (k_1 - r_1).H) - (1.G + k_3.H) - f.G = r_1.H + E

Notice that the RHS is r1.H+Er_1.H + E where EE is the sum of the transaction values.
The RHS is a valid key on HH if and only if E=0E=0*`, i.e. Alice has constructed
the transaction without cheating.

More generally, k1k_1 is the sum of all the blinding factors.

* This is a consequence of how the curves HH and GG were selected initially.

© Tari Labs, 2018-2021. (License : CC BY-NC-SA 4.0)

Where we are so far:

  • Alice knows all the values in the transaction.
  • Bob only knows the shared private key k1k_1, his blinding factor, r1r_1 and subsequently the amount he's receiving.
  • Bob can validate that the transaction amounts sum to zero, but doesn't know the other values.
  • Alice knows the private key, k1k_1, but not r1r_1, so can't spend Bob's Tari, since she can't derive the
    private key sum from this information.
© Tari Labs, 2018-2021. (License : CC BY-NC-SA 4.0)

Proof of ownership

Bob signs an empty string with r1r_1 which proves that he knows r1r_1.This
signature is submitted for inclusion to the blockchain along with the transaction details.

A validator / node then only has to check that

  • EE is a valid public key on HH.
  • That the signature Bob provides corresponds to the public key EE
© Tari Labs, 2018-2021. (License : CC BY-NC-SA 4.0)

One last thing

There's still a flaw in this procedure though.

Alice could have spent a 1 Tari output, giving 2 to Bob, and -1 in change to herself,
thus creating 1 Tari out of thin air.

© Tari Labs, 2018-2021. (License : CC BY-NC-SA 4.0)

Range proofs

To prevent, this, Alice needs to provide a set of range proofs for each amount
she receives, proving that the (masked) values lie between 0 and 2642^{64} (exclusive).

Similarly, Bob provides range proofs for the value he is receiving.

The details of these proofs are beyond the scope of this presentation. But some comments:

  • To complete the range proofs you need the private keys, hence Bob derives the RP for his blinded value.
  • Range proofs add considerable overhead to the transaction.
© Tari Labs, 2018-2021. (License : CC BY-NC-SA 4.0)

Transaction summary

A MimbleWimble transaction includes the following:

  • From Alice, a set of inputs, that reference and spend a set of previous outputs.
  • From either / both, a set of new outputs that include:
    • A value and a blinding factor (which is just a new private key)
    • A range proof that shows that the value is non-negative.
  • An explicit transaction fee, in clear.
  • A signature, using the excess blinding value and using it as a private key.
© Tari Labs, 2018-2021. (License : CC BY-NC-SA 4.0)