HeliosLang / compiler

Helios is a DSL for writing Cardano smart contracts. This library lets you compile Helios scripts and build Cardano transactions.
https://www.hyperion-bt.org/helios-book
BSD 3-Clause "New" or "Revised" License
139 stars 30 forks source link

RFC: Enhancement: Aux Data / Metadata Obfuscation #97

Closed gavinharris-dev closed 11 months ago

gavinharris-dev commented 1 year ago

RFC

Enhancement: Aux Data / Metadata Obfuscation

Summary

Native Asset minting services sometimes use the ability to provide only the Metadata Hash and not the actual Metadata. This results in the Asset Mint not revealing the final Metadata until the Asset is submitted to the blockchain.

This RFC is to discuss possible solution to the way that Helios could support this feature.

Motivation

As discussed in the Summary, this feature is used by Native Asset minting services to obscure the Metadata of the Asset until the transaction is submitted to the blockchain. This is done to prevent gaming mints by users who would be able to review the traits of the Asset before minting and then decide not to mint if the traits are not desirable.

Detailed design

The proposal is to extend the current Metadata type within Helios. Instead of this being:

@typedef {{map: [any, any][]} | any[] | string | number} Metadata

I propose that we change this to a class and allow users to provide an "Obfuscation" function that will be called when the metadata is converted to CBOR. Helios could then provide some default Obfuscation functions that could be used by the user; for example a CIP25 function could be provided which would know how to navigate through the CIP25 data structure and overwrite the attributes with random data of the same size (this should then not impact the size of the Transaction and so allow for correct fee calculation).

So something like:

class Metadata {
  #data
  #obscuringFn

  constructor(data, obscuringFn = (data) => data)) {
    this.#data = data
    this.#obscuringFn = obscuringFn
  }

  get data() {
    return #obscuringFn(this.#data)
  }

  get raw() {
    return this.#data
  }
}

Then within the code the currently references Metadata we would need to access the data getter. The raw getter is to be used by the hashing process so that we get the valid "Hash" within the Transaction Body (position 7).

I am also thinking that a new property could be provided to the Tx::toCbor and Tx::toCborHex methods that would instruct the processes to use the raw getter rather than the data getter resulting in the "Hash" being the same as the raw data.

Drawbacks

For transactions created purely client side this is absolutely pointless; anything on the client would be absolutely visible to the client. This would only be useful for transactions created server side. Also the signing client would be required to send the "signed" transaction back to the Server when the correct Metadata could then be 're-attached' to the transaction.

I am not sure what would happen if a user intercepted the transaction before it was sent back the the server to have the Metadata properly attached. In this cast the Aux Data Hash would be different to the actual data provided and so I assume that the Transaction would be rejected. However I have not tested this.

christianschmitz commented 1 year ago

Forgive me for asking: would it be possible to simply remove the metadata from the tx sent to the client for signing, or would wallets throw some weird error that the metadata doesn't correspond to the metadata-hash (aka. aux data hash) ?

gavinharris-dev commented 11 months ago

Removing the Metadata worked a charm! Closing as this is now complete.