Skip to content

Latest commit

 

History

History
165 lines (117 loc) · 8.34 KB

0035-verifiable-burning.md

File metadata and controls

165 lines (117 loc) · 8.34 KB

Summary

Create a way to provably burn funds which can be audited trustlessly by anyone.

Motivation

Burning means destroying funds (or, rendering them unspendable).

There are a few reasons this may be done:

  • To adjust the supply of a synthetic asset
  • To create a deflationary pressure on a token

Particularly, MCIP #25 will provide the foundations for synthetic assets in MobileCoin.

It is quite easy to make funds unspendable by just sending them to a random public address. If the public address is generated by hashing to curve, then it is infeasible for anyone to find the corresponding private keys, so no one can find and spend this money.

However, in applications, we generally want burning to be transparent and auditable, so that anyone can easily verify when and how much funds were burned in this way.

This purpose is served if the view private key of the burn address is known to everyone, so that they can view key scan to see the provably burned funds (and read the MCIP #3 memos on the burned funds, which may also be useful.)

Therefore, we construct and standardize a burn address such that the view private key is a known constant, and the spend private keys are unknowable.

Guide-level explanation

This proposal creates a standard burn address, such that the view private key is known.

To provably burn funds, simply send them to the burn address. You may attach a memo if this serves your purposes.

To verify that burning occurred, use the view private key to the burn address and view-key scan the entire blockchain. Every provably burning event will be revealed, and you can see the block index, the amount, and read the memo field.

Reference-level explanation

The burn address construction and rationale is as follows:

The BURN_ADDRESS_VIEW_PRIVATE_KEY is a curve25519 scalar, and is a constant known to everyone.

pub const BURN_ADDRESS_VIEW_PRIVATE: Scalar = Scalar::from_bits([1u8; 32]);

The bit pattern [1u8; 32] was chosen arbitrarily. It is the next simplest bit pattern to write in code after [0u8; 32]. We did not choose to make this scalar zero, because, zero is the "funniest number in cryptography" and sometimes leads to degeneracies.

The burn_address_spend_public key is a ristretto point, intended to be a "nothing up my sleeve" number, created transparently by hashing to curve.

In all previous instances where MobileCoin has required such a Ristretto point, we achieve this by fixing a string constant that describes the purpose of the Ristretto point, and hashing this to curve using the Blake2b hash function.

pub const BURN_ADDRESS_DOMAIN_SEPARATOR: &str = "mc_burn_address_spend_public";

fn burn_address_spend_public() -> RistrettoPoint {
    let mut hasher = Blake2b::new();
    hasher.update(BURN_ADDRESS_DOMAIN_SEPARATOR);
    RistrettoPoint::from_hash(hasher)
}

The final step of the construction is the burn address view public key.

Because every public address in MobileCoin is actually a subaddress, the burn address must also conform to subaddress derivation rules, in order for view key matching to work as intended.

fn burn_address_view_public() -> RistrettoPoint {
    BURN_ADDRESS_VIEW_PRIVATE * burn_address_spend_public()
}

That is, the product of account view private key, with subaddress spend public key, is equal to the subaddress view public key.

This identity can be verified by inspecting the MobileCoin subaddress derivation implementation, or by referring to Mechanics of MobileCoin.

Drawbacks

None that we are aware of.

Rationale and alternatives

We believe that this proposal is the simplest approach that could possibly work.

An alternative which was proposed initially did not derive view public by the product of view private and spend public. However, this corresponds to an "old-style" public address and not a subaddress. Currently the MobileCoin transaction builder only supports subaddresses, and we would have to bring back support for sending to the old-style addresses if we wanted to support sending to such a burn address and having view key scanning work. Making the burn address a subaddress avoids all of that work and maintenance burden.

To see that the proposal indeed works, we have to verify that there is no way to spend the burned funds.

Intuitively, we should believe this claim, because the only information we have about the burn address is basically its "view key" in the terminology of CryptoNote. That is, we have the public address, and the view private key. If this data alone can be used to spend the funds, that indicates a design flaw in the transaction protocol. However, it is conceivable (in fact, likely) that for almost all view keys, the view key is not enough for the attacker to figure out how to spend the funds, but for a small number of pathological view keys, it is enough. In the rest of this section we will demonstrate that the burn address we picked is not pathological in this way.

In order to spend the burned funds, an attacker needs to be able to obtain the subaddress spend private key corresponding to the burn address. Therefore, our goal is to show that it is infeasible to learn that subaddress spend private key. (This condition also implies that the account spend private key is infeasible to learn, since that key could be used to derive the subaddress spend private key.)

The subaddress spend private key is the root of the subaddress spend public key, relative to the Ristretto basepoint. So this means, solving the discrete logarithm problem for the subaddress spend public key, given the additional information available about the burn address.

The security argument has two steps:

  • First, we claim that the subaddress spend public key is pseudorandom. If there is an algorithm which, given the burn address and burn address view private key, produces the spend private key with high probability, then this algorithm also works with high probability when the construction is modified so that the spend public key is chosen uniformly at random.

    This claim can be justified by thinking of Blake2b as a random oracle. (There are other less powerful assumptions that we could make here, but in the interest of brevity we will omit discussion.)

    Another way to think about it is that we are claiming that the spend public key we constructed is a ``nothing up my sleeve number'' and there is no way that it could have been manipulated to have non-random properties. (This assumption is also used to construct Pedersen generators for MobileCoin amount commitments.)

  • Second, if there is an algorithm A which given a random point, the scalar [1u8; 32], and the product of that random point and that scalar, finds the discrete log of the point with high probability, then this is also an algorithm for solving discrete log, since for any point, we can efficiently multiply it by [1u8; 32], and then we would be able to use A as a black box to solve discrete log with high probability for random inputs. This directly contradicts the hardness assumption for discrete log in curve25519.

Thus, we have shown by reduction to discrete log that it is intractable to find the subaddress spend key for these funds.

This security argument also shows why it isn't important for the view private key to be chosen by hashing.

Prior art

Thanks to @ChristianOudard who made a proof-of-concept based on randomized public addresses.

Unresolved questions

None at this time.

Future possibilities

It may be desirable some day to make the burn address a Fog address, to make the auditing step more efficient. However this ties the standard burn address to a fog service provider, so we will skip this for now.