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

CIP-0148? | Tag / Redeemer field in TxOut #735

Open
wants to merge 18 commits into
base: master
Choose a base branch
from

Conversation

colll78
Copy link
Contributor

@colll78 colll78 commented Jan 8, 2024

We propose to allow the attachment of arbitrary, temporary data to transaction outputs within the script context. This data, akin to redeemers in their operational context, is intended to be used exclusively during the execution of Plutus scripts and thus are not recorded by the ledger. This will facilitate a wide variety of smart contract design patterns, one of which can be used as a general solution for double satisfaction without sacrificing script composability.


(proposal rendered from branch)

@colll78 colll78 changed the title CPS-???? | Tag / Redeemer field in TxOut CIP-???? | Tag / Redeemer field in TxOut Jan 8, 2024
@rphair
Copy link
Collaborator

rphair commented Jan 23, 2024

@colll78 we're not adding this for discussion in today's CIP meeting, where new proposals are normally introduced in Triage, because of the Draft status (as also with #749). Please feel free to leave it in this state as long as you need... then we will proceed to meeting discussion as well as more rigorous community review (though leaving it here for public comment now is also welcome).

@colll78 colll78 marked this pull request as ready for review January 23, 2024 14:33
@colll78
Copy link
Contributor Author

colll78 commented Jan 23, 2024

@colll78 we're not adding this for discussion in today's CIP meeting, where new proposals are normally introduced in Triage, because of the Draft status (as also with #749). Please feel free to leave it in this state as long as you need... then we will proceed to meeting discussion as well as more rigorous community review (though leaving it here for public comment now is also welcome).

Whoops, I didn't mean to set this as a draft.

@rphair
Copy link
Collaborator

rphair commented Jan 23, 2024

@colll78 Due to last minute status change this has been added to Triage (not time for full technical review; just an introduction) at today's meeting: https://hackmd.io/@cip-editors/80

@Ryun1
Copy link
Collaborator

Ryun1 commented Feb 4, 2024

Input from the IOG Plutus and Ledger teams would be appreciated here 🙏
@michaelpj @lehins

Comment on lines +115 to +127
transaction_witness_set =
{ ? 0: [* vkeywitness ]
, ? 1: [* native_script ]
, ? 2: [* bootstrap_witness ]
, ? 3: [* plutus_v1_script ]
, ? 4: [* plutus_data ]
, ? 5: [* redeemer ]
, ? 6: [* plutus_v2_script ]
, ? 7: [* plutus_v3_script ]
, ? 8: [* output_tag ] ;
}

output_tag = [ index: unit, data: plutus_data ]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Including this information in the witness set might be an attack vector.

The user signs the transaction body, not the witness set.

That means that once transaction is signed the witness set might still change, and the signature would be correct.

That implies the user agreed to sign something that is later modified.

This is not a problem for redeemers because usually the information present on redeemers is validated in the contract, so if an attacker modifies it, a carefully designed contract will fail.

In the example use case of the "TxOutRef in output datum" that information is indeed in the datum, which is part of the tx body, which is signed and hence immutable once signed (or else the signature is invalid).

if we move this info outside the body the TxOutRef can be modified after signing, leaving the contract vulnerable to double satisfaction.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also modifying the redeemer indirectly causes the body to be invalid, because redeemers and datums in the witness set are used to calculate the scriptDataHash

modifying these will result in a different scriptDataHash, hence the body is invalid

Copy link
Contributor

@lehins lehins Feb 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The user signs the transaction body, not the witness set.

The user does sign some parts of the witness set (redeemers and datums) indirectly through the script hash integrity check.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that is correct I corrected myself in the coment

Copy link
Contributor Author

@colll78 colll78 Feb 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right the idea would be for the user to sign this information the exact same way they sign redeemers and datums (ie adjust script hash integrity check accordingly). I will update this CIP to reflect that.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also move the redeemer in the body in the process?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it would be best if redeemers were directly in the transaction body and I would fully support a separate CIP to that end, however, given that currently they are signed via scriptDataHash I don't want to introduce inconsistency by moving these into the body in which case tooling would have to accommodate them differently than they do normal redeemers. The idea is to keep them as close from an implementation perspective to transaction redeemers to lower the implementation burden.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@colll78 trust me, scriptDataHash is much worse than a small inconsistency

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we not then create a CIP to move redeemers into the tx body?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also move the redeemer in the body in the process?

Should we not then create a CIP to move redeemers into the tx body?

I've discussed this very same idea on multiple occasions.
I am not sure if we need a CIP about it, since it shouldn't be that complicated to implement and I suspect everyone would be in favor. But, it might be a good idea to create a CIP for visibility. So, if you still think we need a CIP for it, then I can create one or maybe someone from the community would be willing to step in.

Copy link
Contributor

@michaelpj michaelpj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like it: it adds a kind of weird dangling feature that is useful in this one specific case, and otherwise doesn't mean anything. But I acknowledge that it's a reification of the pattern people currently use.

What I would like is some more principled solution to the double satisfaction problem, which we don't have.

So I guess it's a -0 from me: I would prefer not to do this but if there's lots of support and no alternative I wouldn't block something like this.

```
The intention of the above contract is much clearer, the contract itself is more efficient, and associated transactions do not need to permanently add unwanted data to the chain (unlike the inline datum, reference script solutions). The tags can also be used more generally to convey information about the output to all the validators in the transaction (ie `tag = FullfilledSwapOrder` might signify that this is a fulfilled swap order from protocol XYZ or `tag = SignedOracleObservation BuiltinByteString Integer` might contain a signed message from an oracle that attests that the Value contained in the output is worth X USD).

We already have redeemers associated with each script to provide the smart contract with information that is only relevant during execution for similar reasons (ie redeemers allow us to associate arbitrary data with a script). This would be to TxOuts what Redeemers are for scripts, allowing us to associate arbitrary data (relevant only during Phase 2 validation) to outputs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This made me wonder why you can't in fact use redeemers.

If a particular script execution needs to know which transaction output is "it's" output for some purpose, then you can put the index of that output into the redeemer.

The answer (I think) is that for double-satisfaction you need exclusivity: with the redeemer solution each redeemer has its own mapping and nothing ensures they don't overlap. With output tags you have (I assume) a single tag.

That does sit a little awkwardly, however. Why shouldn't you have multiple tags? What if you do want to use a single output for two purposes in a legitimate way? e.g. "this is the payout address for the Ada" and "the permission token goes here".

Copy link
Contributor Author

@colll78 colll78 Feb 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type of output_tag is data, so you can have any arbitrary information you want in the output so you can store whatever you want there.

What if you do want to use a single output for two purposes in a legitimate way? e.g. "this is the payout address for the Ada" and "the permission token goes here".

That is two outputs though right? IE 1 output is "payout for ada" and 1 is "permission token output", in which case you tag each output accordingly.

The issue is that matching the redeemers to the outputs is very expensive and they aren't really designed to facilitate this time data association with outputs so the interface would be awkward.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please elaborate on why using redeemers for this purpose would be awkward?
We can always work on improving the interface, but I want to know why conceptually redeemers can't be used for this purpose?

```haskell
outputTags :: [ (Integer, BuiltinData) ]
```
The `Integer` represents the index of the output in the transaction outputs for which the data is associated to. The issue with this is that without any support for constant-time index lookup, iterating through this list in a plutus validator will eat into the script budget (ex-units/mem/size). This issue becomes especially bad when there are multiple validators that need to lookup the data associated with an output (or outputs) since the traversal of this list must be done redundantly across all such validators. One of the biggest efficiency improvements that DApps received in Plutus V2 was from the fact that Inline Datums made it no longer necessary to iterate through the datum map to find the datum associated with each output. If we went with this approach, we would be reintroducing that bottleneck which seems clearly undesirable.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I would prefer this approach, and for us to just solve the lookup time problem properly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solving lookup problem would be a good thing to do. It has been a year since that comment was made, anyone knows if there any progress in that direction?
CC @zliu41

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - builtin arrays with constant time lookup is coming at the next HF.

## Motivation: why is this CIP necessary?
Often smart contract logic for most DApps involves associating arbitrary data with transaction outputs. Currently, there are a number of design patterns that are used to achieve this association, but each of these design patterns have significant drawbacks. The limitations of existing solutions have made a wide variety of DApps and design patterns infeasable in practice due to script budget constraints and high complexity of required code.

One obvious use-cases for output tags is to prevent the double satisfaction problem. Currently, the most popular solution for double satisfaction is to include the `TxOutRef` of the input in the datum of the corresponding output and then when validating that the output correctly satisfies the spending conditions for the corresponding input the validator checks that the `TxOutRef` of the input matches the `TxOutRef` in the datum of the output. One issue with this solution to double satisfaction is that it breaks general composability since the output won't be able to contain datums used by other protocols (since the datum is already occupied by the TxOutRef of the corresponding input). Another issue with this approach is that this data permanently bloats the size of the chain even though it is only relevant during the execution of smart contracts. The only reason this data is stored in the datum is so that it can be accessed in the context of Phase 2 validation; the data is not actually relevant to future transactions and thus there is no real reason for it to be permenantly stored on the blockchain in UTxOs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure the bloat complain quite lands:

  1. Anything included in transactions goes in the history of the chain forever, so that would apply to tags as well
  2. But: information in datums does bloat the UTXO set, which can be a problem

That is, I would say it's not so much the permanency that's a problem (that happens anyway), so much as the (temporary, but ongoing) UTXO set bloat.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I did not make it clear I was referring to the UTxO set size which is often what is most impactful on the efficiency of indexers for dApps.

@gitmachtl
Copy link
Contributor

just wanna ask if this affects in any way also hardware wallets? because of the memory constrains, hardwarewallets cannot look at whole utxo sets while performing the signing action.

@rphair
Copy link
Collaborator

rphair commented Apr 2, 2024

@colll78 this is lagging in progress a bit and there was a question in the CIP meeting today over some resolutions that weren't recorded. A couple editors including @Ryun1 & @Crypto2099 (I was just taking some notes) + @michaelpj and @fallen-icarus as I remember made the following points:

  • This is relevant to a "composability" problem of transaction outputs from one dApp to be applied as inputs to a potentially different dApp.
  • Within the CIP process there hasn't yet been any other way of dealing with this composability problem other than the one suggested here.
  • However, people are able to deal with composability issues in other ways that don't require the proposed changes... and therefore this solution might only be applicable to the author's own / preferred implementations.

Assuming the above reservations are valid, both @Ryun1 and I (and maybe others) thought this might then be better off as a CPS dealing with composability (and peripherally the "double satisfaction problem"), and suggesting this tagging approach as one means of dealing with it.

@colll78
Copy link
Contributor Author

colll78 commented Jun 17, 2024

@colll78 this is lagging in progress a bit and there was a question in the CIP meeting today over some resolutions that weren't recorded. A couple editors including @Ryun1 & @Crypto2099 (I was just taking some notes) + @michaelpj and @fallen-icarus as I remember made the following points:

  • This is relevant to a "composability" problem of transaction outputs from one dApp to be applied as inputs to a potentially different dApp.
  • Within the CIP process there hasn't yet been any other way of dealing with this composability problem other than the one suggested here.
  • However, people are able to deal with composability issues in other ways that don't require the proposed changes... and therefore this solution might only be applicable to the author's own / preferred implementations.

Assuming the above reservations are valid, both @Ryun1 and I (and maybe others) thought this might then be better off as a CPS dealing with composability (and peripherally the "double satisfaction problem"), and suggesting this tagging approach as one means of dealing with it.

I would like to clarify that this CIP is not designed specifically as a solution to the double satisfaction problem / dApp composability problem. This is a general improvement to the smart contract platform on Cardano that enables a huge range of use-cases that are currently in-feasible. The core value add is the ability to associate arbitrary data with outputs without permanently writing that data to the UTxO set. Sure, it can be used to solve double satisfaction without sacrificing dApp composability (a property that is currently unique to this solution to DS); however, more generally it can be used to do things like tag specific outputs with the USD price of the multi-asset value they contain via a signed oracle message which is associated to the output via this output_tag field. It also could be used to index the location of relevant tokens within the output value map to make onchain token lookups ~O(1); currently searching values is a very expensive and common operation, for instance if you need to find the total number of pool_asset_a in a DEX pool utxo, or if you need to check for the presence of a some state_thread_token (pretty much every dApp on Cardano). This is possible because the location of all tokens in the value of all outputs is known during transaction construction (nice property of deterministic transactions on Cardano), so you don't need to ever perform search on-chain (i.e. valueOf) instead we can just index the location of these tokens via this output_tag field. So, when a contract comes across a TxOut with an output_tag = 6 (idx of state token) it could simply verify that the head of the 6th entry of the value map contains the state token (or provide 2 indices if it isn't the first token with that currency symbol in the value).

It also enables things such as dependent transaction chaining which is a pre-requisite for babel fees. To achieve this, you could use this field to store a TxIn of an input that must be included as a resolving input (see validation zones) for this transaction to be considered valid by the CHAIN level rules for this tx to be included in the block. Since this would be available in the witness set, it would be available during chain level validation without bloating the UTxO set (probably not an exact fit because the update rules and structure needs to be specific for chain level validation).

Likewise this CIP is of critical importance to intent-based operations / smart contract account abstraction. Both of these involve expressing intent offchain which reduces the number of transactions required to execute a user action. For instance, right now when a user wants to interact with a DEX / orderbook they first must create their order (which conveys their intent i.e. to swap X asset A to Y asset B in DEX pool P, or to sell asset A for asset B at exchange rate of E on an orderbook) in a preliminary transaction, and then a second transaction is required to actually fulfil their request (i.e. batch process orders against the pool on an AMM DEX or match orders on an orderbook DEX), furthermore if you want to update your intent (ie. you want to swap your asset A for asset C instead of asset B or you want to increase slippage or update your sell price or even change the asset you are selling) all of these things will require an additional transaction (perhaps multiple). With this CIP, you can provide your intent as a signed message which in turns allows all aforementioned user operations to be fulfilled in a single transaction. The user doesn't need to submit and pay for a transaction to create a swap request / limit order, the instead they can just publicize a signed message that describes their intent (i.e. swap order with XYZ constraints) which can be consumed by dApps directly to allow them to spend funds from the account as long as they do so exactly as intended by the user (as described by the user's signed message). The user can then update their intent without performing a transaction by producing a new signed message that can then (with this CIP) be associated with the relevant input / outputs.

@rphair
Copy link
Collaborator

rphair commented Aug 20, 2024

My reading of @colll78's #735 (comment) is that this proposal is still interesting to the community. However, I still have no idea how this would be validated as a candidate.

Since all the prior response was from the Plutus team I'm tagging this as Plutus category even though it looks like it could be applicable to the Ledger. @zliu41 (@lehins WhatisRT) could you confirm (or change) that category and indicate that this proposal might be admissible?

In the meantime marking this as Unconfirmed since it's been triaged already but not validated as a CIP candidate. @michele-nuzzi @MicroProofs if you see any advantage to bringing it into the CIP meeting for discussion again please make a comment here & we'll put it on the schedule.

@rphair rphair added Category: Plutus Proposals belonging to the 'Plutus' category. State: Unconfirmed Triaged at meeting but not confirmed (or assigned CIP number) yet. labels Aug 20, 2024
@colll78
Copy link
Contributor Author

colll78 commented Feb 28, 2025

Can we have a re-review on this please? Intent systems are an extremely hot topic right now, and this CIP would provide huge value for all such applications.

@rphair rphair dismissed their stale review February 28, 2025 11:31

oops clicked wrong button to submit "comment" review

---

## Abstract
We propose to allow the attachment of arbitrary, temporary data to transaction outputs within the script context. This data, akin to redeemers in their operational context, is intended to be used exclusively during the execution of Plutus scripts and thus are not recorded by the ledger. This will facilitate a wide variety of smart contract design patterns, one of which can be used as a general solution for double satisfaction without sacrificing script composability.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be useful to add a link to an article or something that describes the double satisfaction problem for those who are not familiar with it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"recorded by the ledger" is an incorrect statement. Every bit from every transaction is recorded by the ledger in the blockchain. Instead, it should state: "not recorded in the ledger state".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will facilitate a wide variety of smart contract design patterns

This statement is way too ambiguous. It is unclear what those use cases are. If they are unknown, then we should be stating it clearly. If they are known then then they must be listed here. Most importantly I would like ta have clarity how this Tag will be used for those multiple problems in the same transaction at the same time.

@lehins
Copy link
Contributor

lehins commented Feb 28, 2025

I read through the CIP and I fail to see a drastic difference between this Tag and the spending Datum or Redeemer. When comparing to inline datum the only difference I see Tag would not contribute to the size of UTxO, which is nice, but if the UTxO overhead is the concern then why regular spending datum hash is not a suitable solution? Is it the fact that spending datum must be known upon TxOut creation, while an arbitrary Tag can be supplied during TxOut spending? If that is the case, thenwhy regular redeemers are not a suitable fit? I read this comment, but I can't understand why redeemers are not suitable fit for this purpose either.
In other words how is it different? Adding a redeemer data into the witness set that will be matched up to the input that is being spent vs a Tag that will also be supplied through a witness set for the same output?
Could you please elaborate with an example of a problem that Tag solves that regular spending datum or redeemer cannot? Cause from the perspective of ledger they look and feel extremely similar. Does the problem lie in the efficiency of finding the spending datum or redeemer data for a particular output or is it more of a fundamental issue?

FYI. I am not trying to put holes into the CIP, I am just trying to understand it. I don't really write plutus scripts, so it is hard for me to see the use case.

With respect to implementation, as far as I understand it, there are a few things that would have to be done on the ledger side in order to accomodate this CIP:

  1. Adding a new field to the witnesses
  2. Make this field participate in the most loved feature: script integrity hash calculation
  3. Change definition of TxOut for PlutusV4 to contain an optional Tag
  4. Resolve all Tags and stick each Tag into the corresponding TxOut representation in the TxInfo part of the Plutus Context.

Final question is why it would be a useful concept only for outputs? Why not add this feature to all other spending purposes? For example a more general solution that I could envision would be adding an extra field to a redeemer: an optional Tag and then on the Plutus side we would add this Tag to all the matching places that are unlocked with a script in that transaction. Or even avoid adding a concept of Tag completely and just add that Data from redeemers to each individual thing that is locked by a script.

To sum up my understanding of this CIP and how it compares to existing features:

  • Unlike inline spending datum, Tag does not contribute to UTxO size
  • Unlike spending datum and inline spending datum Tag does not need to be known during addition of TxOut to UTxO
  • Unlike redeemer, Tag would be readily available in the TxOut, as far as the script is concerned instead of relying on expensive operation that matches the redeemer data with the TxOut

Is this a correct summary?

The reason why I am asking all these questions is to see if this is indeed the simplest and most versatile approach that we can take in order to solve the problem that is outlined in the "Motivation".
In other words, maybe we can do something to make existing solutions economically viable, instead of inventing a totally new approach? i.e. maybe we can solve this problem instead:

The limitations of existing solutions have made a wide variety of DApps and design patterns infeasable in practice due to script budget constraints and high complexity of required code.

I would like to invite the author of the CIP and other parties that interested in this CIP to join the next Ledger Working Group Meeting #13 on March 10th, so we could discuss this in more detail. Without proper understanding of this feature it will be hard for us to create an accurate implementation, so I would really like to understand what is this we are getting into here.

@lehins
Copy link
Contributor

lehins commented Feb 28, 2025

I was thinking more about it and maybe my confusion stems from misunderstanding which outputs will be getting the Tag? Is it the desire of this CIP to add Tags to outputs that are being created by the transaction or the ones that are being spent by the transaction?

colll78 and others added 5 commits February 28, 2025 10:56
@colll78
Copy link
Contributor Author

colll78 commented Feb 28, 2025

I read through the CIP and I fail to see a drastic difference between this Tag and the spending Datum or Redeemer. When comparing to inline datum the only difference I see Tag would not contribute to the size of UTxO, which is nice, but if the UTxO overhead is the concern then why regular spending datum hash is not a suitable solution? Is it the fact that spending datum must be known upon TxOut creation, while an arbitrary Tag can be supplied during TxOut spending? If that is the case, thenwhy regular redeemers are not a suitable fit? I read this comment, but I can't understand why redeemers are not suitable fit for this purpose either. In other words how is it different? Adding a redeemer data into the witness set that will be matched up to the input that is being spent vs a Tag that will also be supplied through a witness set for the same output? Could you please elaborate with an example of a problem that Tag solves that regular spending datum or redeemer cannot? Cause from the perspective of ledger they look and feel extremely similar. Does the problem lie in the efficiency of finding the spending datum or redeemer data for a particular output or is it more of a fundamental issue?

Fundamentally, a redeemer exists to provide information relevant for the execution of the associated script. It is a mechanism by which users can express how they would like to interact with that script. The redeemer often describes the type of interaction the user would like to perform, and information relevant to the successful execution of that action. Furthermore, the information contained by the redeemer is only relevant for the execution of the specific transaction and is entirely irrelevant for subsequent transactions (otherwise it would be stored in the datum). This CIP proposes the introduction of information that, like redeemers is only relevant to the current transaction (and thus should not be stored in the UTxO set) but where redeemers provide information relevant to the execution of a particular script, the optional Tags proposed by this CIP provide information relevant to a given TxOut (since TxInInfo contains a TxOut the tag information could provide additional information about that input to all scripts executing in the transaction, and of-course since outputs are TxOut tags could also be used to provide information about an output to all scripts executing in the transaction)

The core use-cases I have detailed so far are:

  1. Intent-based operations / smart contract account abstraction
  2. Convey general purpose information about the output to all the validators in the transaction (such that this information can be consumed by any validator, without any specific knowledge of the structure of the smart contract associated with this output). The format of this information can be established by standards.
  3. Solution to the double satisfaction that does not sacrifice dApp composability
  4. Index relevant information within a TxOut that can be consumed by validators with specific knowledge of the purpose of this output.

I will expand on why redeemer / spending datums are not adequate for the above use-cases in the CIP meeting next Tuesday.

To sum up my understanding of this CIP and how it compares to existing features:

  • Unlike inline spending datum, Tag does not contribute to UTxO size
  • Unlike spending datum and inline spending datum Tag does not need to be known during addition of TxOut to UTxO
  • Unlike redeemer, Tag would be readily available in the TxOut, as far as the script is concerned instead of relying on expensive operation that matches the redeemer data with the TxOut

Is this a correct summary?

Unlike redeemer (which provides information relevant to the execution of a specific script, Tag provides information about a given TxOut (could be a script input, could be a public key input, could be an output that goes to a script or to a public key address). Tag is not explicitly to provide information relevant to the execution of a specific script, instead it exists to provide information relevant to all scripts in the transaction. If a transaction output has the tag:

newtype DoubleSatisfactionTag = DoubleSatisfactionTag TxOutRef

This indicates to all the scripts executed in the transaction that this tag should only be used to satisfy the spending conditions of the specific input (identified by the TxOutRef in the tag). Say I have a market order on an orderbook selling 5 Foo token for 10 Ada, the orderbook spending conditions allow them to unlock my UTxO if their transaction contains an output to the receiverAddress I put in the datum of my sell order with at-least 10 Ada. Say that I also have an order on an NFT marketplace and am selling my NFT for 10 Ada, the marketplace contract allows anyone to claim the UTxO containing my NFT if the transaction contains an output to the receiverAddress that I put in my marketplace UTxO that contains at-least 10 Ada.

The orderbook redeemer is:

data OrderAction
  = Cancel 
  | PartialFill Integer
  | CompleteFill 
  deriving stock (Generic)

The NFT marketplace redeemer is:

data MarketPlaceOrder =
  PurchaseNFT
  | CancelSale
data MarketPlaceOrderDatum = 
 MarketPlaceOrderDatum {
   ...
   salePrice :: Value 
   receiverAddress :: Address 
   receiverDatum :: BuiltinData 
   }

Someone comes along and builds a transaction that spends the UTxO at the orderbook contract with my 5 Foo tokens and in the same transaction spends the UTxO with my NFT at the marketplace contract and includes one output to my receiverAddress with 10 ada. The transaction succeeds, they were able to purchase my 5 Foo tokens and my NFT with 10 Ada (it should have required 20 ada).

Okay no problem, let's fix this using spending datums, now we modify the orderbook contract and the marketplace contracts as follows:
There must be an output to receiverAddress containing value greater than or equal to the sale price AND the datum of that output must contain TxOutRef that uniquely identifies the order that is being filled (the TxOutRef of the UTxO being unlocked).

Great! Now we have solved the double satisfaction problem! Whoops, the receiverAddress is a smart contract for GOO marketplace platform that is selling GOO tokens, because when I created my sell orders, I wanted to use the value I receive to buy 10 GOO tokens that I really want that cost 20 Ada. But the GOO marketplace smart contract requires a datum in the form of:

data GooOrderDatum = 
   GooOrderDatum { amountToBuy :: Integer, destinationAddress :: Address, destinationDatum :: BuiltinData }

So the orderbook contract, and the NFT marketplace contract were able to solve the double-satisfaction problem by using the spending datum of the output to uniquely tag the UTxOs being unlocked, but in doing-so they broke composability, because they now enforce conditions on the structure of the datum of the outputs that are satisfying the spending conditions (namely they are enforcing that the datum of those outputs must be the TxOutRef of the corresponding inputs). To retain composability, the spending datum of those outputs cannot be occupied, because it needs to be able to match the format expected by the contract corresponding to the receiverAddress.

What if we use tags? Well, now the output is tagged with the TxOutRef associated to the corresponding input (that the output satisfies the spending conditions for) and the datum remains unoccupied and can be whatever format is expected by the script associated with the receiverAddress.

@lehins
Copy link
Contributor

lehins commented Mar 1, 2025

@colll78 Thank you for your response. Your comment definitely made it clearer for me why spending datums are not a suitable solution to the problem. It is still unclear to me why redeemers can't be used to solve this problem.

It might be a very naive question, but please bare with me. As a thought experiment, in order for me to understand the problem better, here is how I could envision redeemer being used for attacking this problem. Note, I am not trying to argue that this is a better approach to what is being suggested in the CIP. I just want to see if my understanding is sound through checking with you whether such a solution could work at all.

Imagine this transaction with UTxO, where 1 Foo == 10 ADA and 1 Bar == 50ADA

utxo = UTxO
  [ (in0, fooScript: 10 Foo)
  , (in1, fooScript: 5 Foo)
  , (in2, barScript: 20 Bar)
  , (in3, 50 ADA)
  , (in4, 100 ADA)
  , (in5, 1000 ADA)
  ...
  ]
Tx
  { body = TxBody
    { inputs = [in0, in1, in2, in3, in4, in5]
    , outputs = [out0: 50 ADA, out1: 100 ADA, out2: 1000 ADA, out3: 15 Foo, out4: 20 Bar]
    }
  , wits = TxWits 
    { redeemers =
       [ (Redeemer (Spending 0), (Data [arg0, "Foo", in4, out1], exUnits0)
       , (Redeemer (Spending 1), (Data [arg1, "Foo", in3, out0], exUnits1)
       , (Redeemer (Spending 2), (Data [arg2, "Bar", in5, out2], exUnits2)
       ]
    }
  }

So, in such a transaction both fooScript and barScript will see all of the redeemers. My question is that why can't those scripts inspect the data passed in those redeemers in order to ensure that they verify double satisfaction? Is it because DApp writers would have to agree on predefined format for the redeemer data? Or is this approach has some sort of vulnerability that can be exploited to bypass double satisfaction verification? Or is it an issue of efficiency?

I can see how this Tag solution is a more "type safe" and more efficient approach to dealing with problem, when comparing to the one that uses redeemers. But, it doesn't really feel to me versatile enough. For example:

  • ADA could be coming from many different places (certificate refunds, reward account withdrawals)
  • Ada could be going to many different places (paying deposits, fees, donating to treasury, etc.)
  • NFTs can be minted
  • inputs and outputs are unlikely to contain exact amounts to satisfy those kind of trades precisely, so it is unlikely that there will be a perfect match between ADA and NFT swaps like that. So even with Tags you'd have to have some sort of agreed upon format for the data that is being placed in those Tags.

It feels to me like this problem is a more fundamental one that could use a more versatile and standardized solution. I am not going to pretend like I have a better solution at this moment, but I have never thought about this problem until now.

@lehins
Copy link
Contributor

lehins commented Mar 1, 2025

An idea just popped into my mind. I haven't thought it through very well yet, but, I think it sounds sensible. What if we add a concept of a "Claim". Every script would have a capability to claim parts of the transaction and no two scripts could claim the same part of the transaction. Here is a sample data type:

data Claim = 
  = ClaimInput TxIn Value
  -- ^ Specifies which input to claim and which portion of it will be claimed by the script
  | ClaimWithdrawal RewardAccount Coin
  -- ^ Claim ADA that is coming out of a withdrawal
  | ClaimRefund CertIx Coin
  -- ^ Claim ADA that was refunded in one of the unregistration certificates (either DRep or Staking Credential)
  | ClaimMint Value
  -- ^ Claim a positive value that was minted in this transaction

Then we'd add this claim to a redeemer:

data Redeemer = Redeemers
  { unRedeemers :: Map (PlutusPurpose AsIx era) (Data era, ExUnits, [Claim])}

This would allow for a whole lot more flexibility:

  • Multiple scripts would be able to claim parts of the same input.
  • Scripts could claim parts of the transaction that would be otherwise inaccessible. Eg. you'd be able to buy NFTs with rewards.
  • You could mint multi-assets and other scripts could claim those mints.
  • You could burn your multi-assets that you've claimed in the same transaction.

Ledger rules would then verify that there are no overlaps between any two claims:

  1. No two scripts try to claim same parts of the resource in the transaction.
  2. Total claims do not exceed resources that are available in the transaction.

Two things that I like about this solution is that it would be standardized and there would be no extra logic required from the DApp writers (thus practically free from the perspective of execution units). It would be up to transaction builder to specify which part of the transaction maps to which validator. Naturally, those claims would be available to the script, so if desired those scripts would be able to confirm that enough resources were claimed to satisfy the validator, but at least they wouldn't need to worry about any other script claiming the same resources.

I also believe that those claims could be specified for all plutus versions, with one limitation that only PlutusV4 would be able to see those claims in their context.

FYI, current CIP is quite a bit easier to implement from the Ledger perspective, so in a sense I am piling up more work on our shoulders, but I believe that it would be totally worth it. What I am suggesting above would be a much safer solution IMHO, since there would be no ambiguities on how this feature suppose to be used, which is not the case with Tags.

This approach as I described does not provide a mechanism to check where the money is going (i.e. ADA went to Alice that spend her NFTs), but I don't think it should even matter. In other words checking that no resource is used for two different purposes, sounds to me like a well defined solution to the double satisfaction problem.

@colll78 Thoughts?

CC @WhatisRT What's your opinion on this suggestion.

If this solution sounds sensible to you guys I could write up a more detailed CIP.

@colll78
Copy link
Contributor Author

colll78 commented Mar 2, 2025

this Tag solution is a more "type safe" and more efficient approach to dealing with problem, when comparing to the one that uses redeemers. But, it doesn't really feel to me versatile enough. For example:

  • ADA could be coming from many different places (certificate refunds, reward account withdrawals)
  • Ada could be going to many different places (paying deposits, fees, donating to treasury, etc.)
  • NFTs can be minted

@colll78 Thank you for your response. Your comment definitely made it clearer for me why spending datums are not a suitable solution to the problem. It is still unclear to me why redeemers can't be used to solve this problem.

It might be a very naive question, but please bare with me. As a thought experiment, in order for me to understand the problem better, here is how I could envision redeemer being used for attacking this problem. Note, I am not trying to argue that this is a better approach to what is being suggested in the CIP. I just want to see if my understanding is sound through checking with you whether such a solution could work at all.

Imagine this transaction with UTxO, where 1 Foo == 10 ADA and 1 Bar == 50ADA

utxo = UTxO
  [ (in0, fooScript: 10 Foo)
  , (in1, fooScript: 5 Foo)
  , (in2, barScript: 20 Bar)
  , (in3, 50 ADA)
  , (in4, 100 ADA)
  , (in5, 1000 ADA)
  ...
  ]
Tx
  { body = TxBody
    { inputs = [in0, in1, in2, in3, in4, in5]
    , outputs = [out0: 50 ADA, out1: 100 ADA, out2: 1000 ADA, out3: 15 Foo, out4: 20 Bar]
    }
  , wits = TxWits 
    { redeemers =
       [ (Redeemer (Spending 0), (Data [arg0, "Foo", in4, out1], exUnits0)
       , (Redeemer (Spending 1), (Data [arg1, "Foo", in3, out0], exUnits1)
       , (Redeemer (Spending 2), (Data [arg2, "Bar", in5, out2], exUnits2)
       ]
    }
  }

So, in such a transaction both fooScript and barScript will see all of the redeemers. My question is that why can't those scripts inspect the data passed in those redeemers in order to ensure that they verify double satisfaction? Is it because DApp writers would have to agree on predefined format for the redeemer data? Or is this approach has some sort of vulnerability that can be exploited to bypass double satisfaction verification? Or is it an issue of efficiency?

The redeemer exists to provide information relevant to the execution of a specific script, as such it, it contains a format that is only comprehensible to the script itself. In the above example, fooScript can barScript can indeed view the redeemers list, but for fooScript to understand the redeemer of barScript it will need specific knowledge about the construction of that script, if the redeemer of a script is BuiltinData encoded in constructor format (ie. Constr Index [BuiltinData]) then the fooScript will need to know what field the fields in barScript mean to meaningfully interact with them (say it just searches for a TxOutRef, how can it know that the purpose of that TxOutRef is to uniquely identify the inputs? What if there are multiple input sources? What if a script uses BuiltinData encoded as BuiltinList [BuiltinData] instead of the constructor format?

Even in an ideal world, where we get every single script author to follow a standard that enforces the redeemer is encoded in constructor format, and that the first field in the constructor of any spending redeemer should be a BuiltinList [BuiltinData] that identifies all the outputs that satisfy the spending conditions for that input, this solution is simply impractical. Imagine we have 40 inputs, from 40 different scripts, for fooScript to know that some arbitrary TxOutRef, txOutA, is used exclusively to satisfy the spending conditions for inputA, it will need to traverse every spending redeemer in the transaction (40) and check that txOutA is not identified as the satisfying output for the redeemer of any other script execution. Then all 39 other scripts in the transaction need to do the same, now we have traversed and decoded a list of 40 redeemers in 40 different script executions in the transaction, this would be impossible. With tagging, you don't need to traverse anything, the information you need is directly in the outputs, so the execution of 40 scripts is feasible without blowing up budget.

Again, I would like to explicitly clarify that the purpose of tags is not exclusively as a solution to double-satisfaction, this is just a single example in which the ability to provide information relevant to TxOuts directly is powerful. The alternative that you are proposing cannot address the other use-cases I mentioned (intent-based operations, account-abstraction, etc).

@rphair rphair changed the title CIP-???? | Tag / Redeemer field in TxOut CIP-0148? | Tag / Redeemer field in TxOut Mar 7, 2025
Copy link
Collaborator

@rphair rphair left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@colll78 as per Tuesday's CIP meeting this was acknowledged as ready for merge as soon as the formalities like CIP number & directory renaming (to CIP-0148) are in place. 🎉

@lehins our understanding of your latest comments is that these are an exploration of this issue with an eye for best practice that @colll78 and colleagues have worked out through engineering trial & error over 3 years or so. So we're assuming that you have no real objections to this unless stated explicitly.

I'm tagging Last Check which puts it on the next meeting agenda (https://hackmd.io/@cip-editors/108) as a failsafe, but @Crypto2099 @Ryun1 as you recall from the meeting (cc @perturbing) this was declared ready to merge before then if there's full editor support & no last-minute objections.

@rphair rphair added State: Last Check Review favourable with disputes resolved; staged for merging. and removed State: Unconfirmed Triaged at meeting but not confirmed (or assigned CIP number) yet. labels Mar 7, 2025
Copy link
Contributor

@lehins lehins left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@colll78, sorry I got distracted by other things and forgot to respond. Thank you for your explanation, it does make it clear to me why existing solutions are unsuitable. I figured that the problem with redeemers would be the fact that data supplied is weekly typed and it would be very hard to have all script writers to agree on a common format. With that in mind, can you please explain to me how is this also not a problem for Tags proposed in this CIP. Tags are expected to be a weekly typed Data as well as redeemers are:

if the redeemer of a script is BuiltinData encoded in constructor format (ie. Constr Index [BuiltinData]) then the fooScript will need to know what field the fields in barScript mean to meaningfully interact with them

What if other scripts try to use tags for something else which would conflict with the solution for double satisfaction that your script is relying on? In other words, from my understanding of this CIP, it also suffers from the exact same problem as redeemers do.

@rphair I understand that @colll78 and other have a lot of experience with this problem and with DApp writing in general, but I am still not yet convinced that this is the best approach possible.

Last thing I want is to implement a feature that we have to support forever, which we end up replacing with something different in a feature era, because this approach turned out to be suboptimal.

What I would like to see is the list of all problems that this approach solves. Cause I was under impression from reading this CIP that the sole reason why it is needed was to solve double satisfaction problem, which turns out is not the case: "The alternative that you are proposing cannot address the other use-cases I mentioned (intent-based operations, account-abstraction, etc)." @colll78 Please forgive me, but I can't find any mention of "account-abstraction" in this CIP.

For example, unless we are talking about something else, intents as I know them, will be solved by a CIP that is already planned to be implemented CIP-118, so this CIP no longer needs to solve it and I am not even sure how it would solve it, to be honest with you.

"account-abstraction" - what is this and how this Tag approach solves it and why is it a problem that we need to solve to begin with?

@rphair In other words, I do object this CIP as it stands right now, because in my opinion it does not have enough information on how it solves the problems it claims to be solving. It does not compare to any other approach that we can take that would solve those problems in alternative ways. For example, what the alternative approach that I suggested that would solve double satisfaction problem has not been considered so far or properly compared to. Are there other solutions that are known to solve the same problem(s).
If this CIP is not clear to me, as a ledger expert, I am sure it will be unclear to many others. So at the very least I would expect some better explanations of the problems and the solution with some examples. In particular:

  • how solving double satisfaction plays together with other purposes Tags will be used for?
  • how this feature works for solving double satisfaction when partial matches of many TxOuts to many TxIns are desired?
  • why we only want to solve these problems for TxOuts and not other sources of value: withdrawals, deposits/refunds, minting?

Keep in mind, that I am not trying to push back on the feature, I am asking for this CIP to be improved, with proper comparison to alternative approaches that we can take (i.e. not the ones that are already available today).

---

## Abstract
We propose to allow the attachment of arbitrary, temporary data to transaction outputs within the script context. This data, akin to redeemers in their operational context, is intended to be used exclusively during the execution of Plutus scripts and thus are not recorded by the ledger. This will facilitate a wide variety of smart contract design patterns, one of which can be used as a general solution for double satisfaction without sacrificing script composability.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"recorded by the ledger" is an incorrect statement. Every bit from every transaction is recorded by the ledger in the blockchain. Instead, it should state: "not recorded in the ledger state".

---

## Abstract
We propose to allow the attachment of arbitrary, temporary data to transaction outputs within the script context. This data, akin to redeemers in their operational context, is intended to be used exclusively during the execution of Plutus scripts and thus are not recorded by the ledger. This will facilitate a wide variety of smart contract design patterns, one of which can be used as a general solution for double satisfaction without sacrificing script composability.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will facilitate a wide variety of smart contract design patterns

This statement is way too ambiguous. It is unclear what those use cases are. If they are unknown, then we should be stating it clearly. If they are known then then they must be listed here. Most importantly I would like ta have clarity how this Tag will be used for those multiple problems in the same transaction at the same time.

```haskell
spendValidator :: BuiltinData -> Integer -> ScriptContext -> ()
spendValidator _ outIdx ctx =
let ownOutputTag = txOutTag ownOutput
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you enforce uniqueness of the Tag? Nothing prevents a user from creating a transaction where all supplied and expected tags have the same value?


If this CIP is adopted, the above validator could be simplified to:
```haskell
spendValidator :: BuiltinData -> Integer -> ScriptContext -> ()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fail to see with this example how it is possible to match the many-to-many relationship that we have for inputs and ouptuts. This example assumes one-to-one relationship.

We already have redeemers associated with each script to provide the smart contract with information that is only relevant during execution for similar reasons (ie redeemers allow us to associate arbitrary data with a script). This would be to TxOuts what Redeemers are for scripts, allowing us to associate arbitrary data (relevant only during Phase 2 validation) to outputs.

## Specification
We extend transaction witness set with a new list of arbitrary data associated with transaction outputs (`output_tags`).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we put them in the TxBody instead of the witnesses. There is no reason why it must be in the witness set. In fact even redeemers didn't have any business being placed in the witness set, so we are considering moving them into TxBody, which would simplify calculation of the script integrity check. Although, this decision is not set in stone yet.

Comment on lines +115 to +127
transaction_witness_set =
{ ? 0: [* vkeywitness ]
, ? 1: [* native_script ]
, ? 2: [* bootstrap_witness ]
, ? 3: [* plutus_v1_script ]
, ? 4: [* plutus_data ]
, ? 5: [* redeemer ]
, ? 6: [* plutus_v2_script ]
, ? 7: [* plutus_v3_script ]
, ? 8: [* output_tag ] ;
}

output_tag = [ index: unit, data: plutus_data ]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also move the redeemer in the body in the process?

Should we not then create a CIP to move redeemers into the tx body?

I've discussed this very same idea on multiple occasions.
I am not sure if we need a CIP about it, since it shouldn't be that complicated to implement and I suspect everyone would be in favor. But, it might be a good idea to create a CIP for visibility. So, if you still think we need a CIP for it, then I can create one or maybe someone from the community would be willing to step in.


Note that although we propose to add `tag` as a field to `TxOut`s in the script context, we don't actually put them there in the CDDL. This is because the purpose of `output_tag` is to hold arbitrary data that associated to the output that is only relevant in the context of evaluating Plutus validators during Phase 2 validation. This data is not meant to be stored in UTxOs.

This means that when constructing the script context the ledger must add each the data in each `output_tag` to the `TxOut` at the matching index in the transaction outputs. If there is a compelling case to be made to introduce this tagging for `TxOut`s in the transaction inputs in the script context (ie to associate arbitrary data to transaction inputs during Plutus validator execution) then this can be extended to introduce a 9th field to the witness set `[* output_tag]` to contain the arbitrary data that the ledger can then associate with `TxOut`s in transaction inputs in the script context.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be a 10th field with an index 9 😉

ownOutput :: TxOut
ownOutput = elemAt outIdx (txInfoOutputs (txInfo ctx))
```
The intention of the above contract is much clearer, the contract itself is more efficient, and associated transactions do not need to permanently add unwanted data to the chain (unlike the inline datum, reference script solutions). The tags can also be used more generally to convey information about the output to all the validators in the transaction (ie `tag = FullfilledSwapOrder` might signify that this is a fulfilled swap order from protocol XYZ or `tag = SignedOracleObservation BuiltinByteString Integer` might contain a signed message from an oracle that attests that the Value contained in the output is worth X USD).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens when one script expects the tag to be FullfilledSwapOrder, while another expects it to be ProtectAgainsDoubleSatsfaction

Moreover we have a much more versatile approach planned to satisfy the swaps/intents use case, which is described in CIP-118

Just i -> i

ownOutput :: TxOut
ownOutput = elemAt outIdx (txInfoOutputs (txInfo ctx))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest not to change the TxOut type itself, this way inputs would not be affected
Is there an assumption that all outputs will require a tag? i.e does it have this type txInfoOutputs :: [(TxOut, Tag)] or this type txInfoOutputs :: [(TxOut, Maybe Tag)]?

```haskell
outputTags :: [ (Integer, BuiltinData) ]
```
The `Integer` represents the index of the output in the transaction outputs for which the data is associated to. The issue with this is that without any support for constant-time index lookup, iterating through this list in a plutus validator will eat into the script budget (ex-units/mem/size). This issue becomes especially bad when there are multiple validators that need to lookup the data associated with an output (or outputs) since the traversal of this list must be done redundantly across all such validators. One of the biggest efficiency improvements that DApps received in Plutus V2 was from the fact that Inline Datums made it no longer necessary to iterate through the datum map to find the datum associated with each output. If we went with this approach, we would be reintroducing that bottleneck which seems clearly undesirable.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solving lookup problem would be a good thing to do. It has been a year since that comment was made, anyone knows if there any progress in that direction?
CC @zliu41

@rphair
Copy link
Collaborator

rphair commented Mar 9, 2025

thanks @lehins for clarifying the position we had assumed in #735 (review). We will consider your latest round of review a checklist for things that need to be agreed upon before moving forward. - cc @WhatisRT (and @polinavino if you want to jump into the discussion about how this might affect the development of "intents" & #862)

@colll78 I'll dial this back from Last Check but editors will keep an eye on the discussion of these review points to see when your two positions start coming together... if & when that happens we will put this on the track to merging it again. If either of you think a CIP meeting discussion would help, just say so and the time will be yours on the next meeting's agenda. - cc @Ryun1 @Crypto2099 @perturbing

@rphair rphair added State: Confirmed Candiate with CIP number (new PR) or update under review. and removed State: Last Check Review favourable with disputes resolved; staged for merging. labels Mar 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Category: Plutus Proposals belonging to the 'Plutus' category. State: Confirmed Candiate with CIP number (new PR) or update under review.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants