Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable transaction support for read-only data inputs #3653

Closed
savaki opened this issue Jul 30, 2021 · 8 comments
Closed

Enable transaction support for read-only data inputs #3653

savaki opened this issue Jul 30, 2021 · 8 comments

Comments

@savaki
Copy link

savaki commented Jul 30, 2021

Area

[x] Plutus Foundation Related to the GHC plugin, Haskell-to-Plutus compiler, on-chain code
[ ] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
[ ] Marlowe Related to Marlowe
[ ] Other Any other topic (Playgrounds, etc.)

Describe the feature you'd like

Allow transactions to include one or more data eUTXO(s). A data utxo is a eUTXO that cannot
be spent, but whose metadata is available to the transaction. This would allow oracle data to
be published once and referenced by many transactions.

More specifically:

  • Allow transactions to specify zero or more data eUTXO(s)
  • Data eUTXO(s) may not be spent
  • Consequently, any redeemer script associated with a data eUTXO will not be executed
  • Datum within the data eUTXO will be available to all scripts within the transaction
  • (Ideally) Transaction would only include a reference to the data eUTXO to not put further strain the tx size limit

Describe alternatives you've considered

Option 1 - Off-Chain

Rather than attempting to store oracle data in a eUTXO, provide the oracle data via as datum
to the transaction. While workable for some situations, this option presents a number of challenges:

  • ensuring trustworthiness of the data
  • the increased code size required for off-chain validation especially in light of the 16k tx limit
  • requirement for off-chain systems to publish the data accessibly
  • handling propagation delay
  • reasonable consistency in the face of on-chain events such as rollbacks

Given the number of hacks to Ethereum smart contracts that have played games with the interaction
of oracle data and on-chain code, the team opted not to pursue this route.

Option 2 - Per Request

In this option, a data eUTXO would be requested prior to being consumed in a transaction. This
mimics the behavior of Ethereum oracles, but rather than a synchronous request, it becomes an
asynchronous request via the blockchain. Given the poor user experience this would entail, the
team quickly dropped this option.

Option 3 - Over-Provision

Using formulas similar to those used by call centers to calculate the number of agents required
to handle a given call volume, a protocol would calculate the number of oracle eUTXO(s) required
to provide the desired level of eUTXO contention. While workable, this solution has a number
of challenges:

  • protocols forced to choose between user experience and cost
  • cost issue exacerbated by 16k tx size limit, possibly requiring multiple transactions per datum
  • protocol burdened with significant code requirements to ensure smooth operation of oracle eUTXO
    • each oracle eUTXO must include NFT to prove authenticity
    • each oracle eUTXO must include redeemer scripts to ensure adversary does not lock up eUTXO

Worse still would be the impact to the blockchain if a number of protocols adopted this approach.
Each protocol would be constantly creating eUTXO(s) that it knew would probably not be consumed.
One could imagine a significant portion of the L1 TPS being used in such a manner.

Additional context / screenshots

Pi Lanningham came across research done by Emurgo, Unlocking The Potential Of The UTXO Model

See the Read-only data inputs within the alonzo-white channel within discord.

Additional discord discussions:

@catch-21
Copy link
Contributor

catch-21 commented Aug 2, 2021

Thanks for raising this @savaki. It seems that this is an old topic and has been discussed many times. There are some proposals to address this, although none are yet agreed. Therefore, I wouldn't expect an implemented solution anytime soon. The recommendation is to use an off-chain solution because on-chain is never going to scale.

We shall leave this issue open for tracking, please use it for future reference. We should add to it if there are future discussions (I'm sure there will be).

@jfischoff
Copy link

The recommendation is to use an off-chain solution because on-chain is never going to scale

Why would on-chain never scale?

If the UTxOs are read-only is there any congestion?

@anton-k
Copy link
Contributor

anton-k commented Nov 20, 2021

I second this issue! this can help a lot with certain type of concurrency.
When we use UTXO as an oracle to query exchange rate or supply some validation constants.

If we don't have it as read only we have to change the reference of the UTXO which makes it impossible to share between users in highly concurrent systems.

If there is debate over implementation maybe it's worth to look at the systems where it is already implemented?
You can have a look at Ergo / ErgoScript they have this feature and it's very useful in UTXO-based systems.

@locallycompact
Copy link

Hi. Where can I read the proposals to address this? What is the kind of modification needed to make this change?

@anton-k
Copy link
Contributor

anton-k commented Nov 21, 2021

@locallycompact Hi! Thanks for willing to take an action on this important enhancement.
You can find detailed description of the feature in the link that @savaki provided Unlocking UTXO model. It describes in detail approach taken by ErgoScript.

TLDR: The basic idea is very simple: we can have read-only inputs on TX which are not spent by TX and we can access their datums and values from validators of other inputs on TX. Main benefit: reuse of UTXO ref of read-only input for many TXs within the block. No need for copy paste update logic.

At the moment every TX transforms set of inputs to the outputs as we destroy/spend every input and create new output UTXOs. Imagine that in TX there can be inputs of special type which are read-only (in Ergo it's called data input). We can access their datums and values but they are guaranteed to be not spent but only included in TX as providers of useful information. Data input don't need redeemer as it is not spent. As non-spending is ensured we can rely on data input reference that it will stay the same within the block and we can reference the same data-input from many TXs.

In current situation we have to transform the UTXO, basically to make kind of Oracle we keep everything the same and spend it back to the same validator. Which prohibits the reuse of the reference to the read-only UTXO

But the data-input feature gives us ability to reuse it within the same Block for many TXs and unlocks concurrency.
and we don't waste TX-execution resources on logic that ensures exact copy paste of the read-only UTXO.

The most common case of usage is imagine that we have trusted exchange rate between currencies and every exchange on the market can include the UTXO that contains that info as read-only and we don't suffer from contention problem (we suppose that exhanges happen more frequently than update of the rate).

Another example: Imagine that two persons bet on some event that will happen in the future. We have trusted authority that will post UTXO with given asnwer to the riddle or scores of the game etc. Both parties put funds to the same box. And then winner can spend the common funds of both guessers if criteria of read-only UTXO posted by trusted oracle matches given answer.

Another useful example: Imagine we build dApp and we expect that there is config with common constants to the dApp, and we expect that parameters of config can change in the future. So for dApp to work properly we include config as data-input and to update the configs we update that config UTXO. And logic of reading stays the same if the datums are compatible and we only update concrete constants within it.

So it can be emulated by current system. But the main benefit of such approach is ability to share the same reference between several TXs within single block. It unlocks useful pattern of concurrency. Another benefit is that we save resources on common exact copy paste pattern logic of read-only UTXO. We use only extra Tx-size in this case.

@locallycompact
Copy link

@anton-k Thank you for the write-up. This matches what I understand so far. I am wondering how to start approaching this and what depth a change this is in the system. I have some questions:

  1. Is this a change purely in Plutus, or at what layer in the architecture currently is there the insistence that every UTXO involved in a transaction must be spent?

  2. When the article talks about potentially updating so-called "proxy boxes" with arbitrary validator changes, how can we then prove properties such as no funds stay locked in the contract in all cases?

@anton-k
Copy link
Contributor

anton-k commented Nov 21, 2021

  1. I'm not sure but I guess that Cardano transaction format can also be affected by this.
    On plutus level (or for TxInfo) we need two separate sets of inputs: ordinary inputs and read-only ones.
    read only have only TxOut's (probably with datums in dataMap) no need for redeemers.

  2. I think we can update them as noormal UTXOs. So when UTXO is placed on the blockchain we don't mark it in any way that it's read only. It also has validator and can be spent and update in this way. Read-only property is only TX-level.

It means that after UTXO update users should use new reference to that UTXO but property of reuse within the block still holds if it's not update on that Block

@michaelpj
Copy link
Contributor

There's now a CIP, please discuss there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants