-
Notifications
You must be signed in to change notification settings - Fork 318
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-0130? | Transaction Pieces #873
CIP-0130? | Transaction Pieces #873
Conversation
@Quantumplation @michaelpj @polinavino This CIP elaborates on what I was talking about in the Validation Zones PR discussion. I think it covers the same use cases with a fraction of the complexity. I'm going to tag other people that have expressed interest in intents: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fallen-icarus thanks for continuing that premise. I've added this PR for introduction to tomorrow's CIP meeting agenda: https://hackmd.io/@cip-editors/94
I would be really happy to keep this evolving along with Validation Zones and any other approaches to intent-based transactions. At some point soon we would need the Ledger team's opinion about feasibility so also tagging them (@lehins @WhatisRT).
This is not a detailed review, since the point at which I could assess all the technical propositions and/or compare/contrast with Validation Zones would be a long time coming: this is just a skim for format consistency, etc., while we get this into the pipeline.
I support this solution as a significantly less complex alternative. A suggestion: smart contracts could get some extra efficiency from this CIP if there is a way to access the current transaction piece inside the script. Oftentimes, a script needs to find a specific input satisfying some conditions. Since transaction inputs are not sorted by the signers, the signers don't have control over the input order. So, in transactions with many inputs, a lot of ExUnits may be spent just on finding the right input, which is usually from the same transaction piece as the script itself. |
I guess this is currently not hw wallet compatible, because hw wallets need a full transaction from a security pov. Its not possible to just sign "anything" with a hw wallet. Arbitrary data can be signed now with hw wallets, but its embedded in the CIP-8 COSE_Sign1 structure to avoid users falling into the trap that they think they sign just some data, but in reality they are signing a transaction with a given hash. Or do i understand this CIP wrong? The hw wallet does not care if a transaction is balanced or not. But without the whole transaction in place the total hash of the transaction would not be correct and so the hw wallet signing would not work. Its already possible - and we do this all the time - to collect multiple witnesses. And a hw wallet can of course provide a witness to a transaction, which is than later assembled into a fully signed transaction. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This appears to me to be mostly a simplified version of the Validation Zones CIP that has a bunch of benefits because of its simplicity, but also some drawbacks. Maybe there is a 'best of both worlds' design that lies somewhere in the middle?
While the cryptographic keys only need to sign the relevant transaction pieces, the smart contracts | ||
would be executed against the full transaction. This requirement enables the current smart contract |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This goes against our current philosophy of preserving the submitted transaction as verbatim as possible. Without a good reason for this, it's probably better to properly reflect this structure in TxInfo
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without a good reason for this, it's probably better to properly reflect this structure in
TxInfo
.
Personally, whichever option minimizes added complexity is my preferred choice. If we preserve the transaction as you are suggesting, the smart contract interface would need a pretty large change and DApps would need to be re-architected. Perhaps keeping the structure in TxInfo
would be better in the long run, but I'm not sure. I do not know what changes would be required on the ledger/plutus side to actually preserve the structure in TxInfo
.
@vlasin If we did preserve the structure, I believe this would address your suggestion.
be able to deterministically derive the full transaction, this instance must be standardized. The | ||
monoid instance requires answering two questions: | ||
|
||
1. What is an empty transaction piece? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You cannot submit an empty transaction anyway, so we don't necessarily need to define this. There is no reason why it needs to be a Monoid
.
Imagine if Alice wants to swap 100 ADA for 50 DJED; this says nothing about how the counter-party | ||
will satisfy her swap. Perhaps Bob (the counter-party) wants to provide the DJED, but it is | ||
currently broken up across three UTxOs. And perhaps he wants the 100 ADA he receives to be stored in | ||
two separate outputs. If Alice specifies only one input placeholder and one output placeholder in | ||
her intent transaction, Bob might be unable to act as her counter-party. If Bob really wanted to | ||
still trade with Alice, he would have to find a way to merge his inputs and outputs into one input | ||
and one output. This may not always be possible and Bob may have to give up on being Alice's |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually quite easy to do with validation zones. Bob just needs to spend his three outputs and Alice's Ada output and negative Djed output, and make two new outputs containing the Ada. The only extra effort is to spend Alice's two outputs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my other comment here.
placeholders and extra transactions just to satisfy these placeholders, the impact Validation Zones | ||
would have on the average block size is likely equivalent to, if not larger than, the impact this | ||
CIP would introduce. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Compared to the validation zones approach, this approach appears to be somewhat simpler indeed, but it also has some restrictions. For example, this approach doesn't allow for atomic batch transactions in general. A transaction piece cannot spend an output generated by another transaction piece in the same transaction. I see this as a major drawback, and it should be discussed here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Atomic batch transactions seems orthogonal to intents (it isn't mentioned in the CPS), but I can still discuss it in the CIP.
@polinavino Perhaps there is a way to use transaction pieces as the foundation for zones?
having enough liquidity. The Validation Zones CIP argues that DApps can just add support for | ||
breaking-off/merging UTxOs so that the liquidity source UTxOs can be forced into the proper forms | ||
for the required placeholders. However, this would dramatically increase the complexity and attack |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see where this is discussed in the Validation Zones CIP. But I also don't see a big problem here, just by going on with the same logic from the last paragraph. A matching transaction can always spend the 'problematic' outputs and then construct the remainder of the transaction as it would construct the transaction piece. I don't see where this impacts 'dramatically increases complexity'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A matching transaction can always spend the 'problematic' outputs and then construct the remainder of the transaction as it would construct the transaction piece. I don't see where this impacts 'dramatically increases complexity'.
I guess I'm just biased. Given there is a path that doesn't require these extra steps, why would you ever take the path of more resistance?
EDIT: Actually, I think the Validation Zones' approach is still an issue. Being able to break-up/merge DApp UTxOs is most likely orthogonal to what the DApp is trying to do. I strongly believe DApps should use the bare minimum level of complexity to accomplish their task since people's livelihoods are literally at stake. Perhaps "dramatically" is an exaggeration in most cases, but "increases complexity" is still accurate and I still think it is bad. Especially since there is an alternative method that doesn't require the extra complexity.
@gitmachtl A transaction piece is literally just a full transaction body that can be unbalanced. Therefore, hw wallets should already be (mostly) capable of signing pieces. If hw wallets can hash/verify/sign a transaction body, then it can hash/verify/sign a piece since they are the same thing.
When signing the piece, the hardware wallet would hash the piece itself. This is all the signer cares about anyway. Since the piece is included in its entirety on chain, users can easily verify their transaction piece was properly included using the hash of the piece. The off-chain tooling would definitely need to be updated to enable this verification, but I don't see anything that would make this difficult/impossible. In this new paradigm, hw wallets only need to be able to sign transaction pieces. You can still have a piece be a fully balanced transaction so there is no loss of functionality with this change. |
@vlasin I'd have to think about this. This would definitely add a lot of complexity and actually require a change to the smart contract interface. I agree there would be some efficiency gains, but since the aggregator can control the order of the pieces themselves, the ExUnits spent can already be minimized quite a bit. I'm not sure if the rest of the gains would be worth the extra complexity. |
maybe i am just confused, but how would an unbalanced transaction be ready for signing? if you change the lovelace/asset value of an output, the hash of the tx would not be the same again. or is it output to a fixed "pseudo" address, and later those transactions are somehow put together? |
You wouldn't change an output after signing. The transaction piece stays unbalanced. The aggregator can then fit unbalanced transaction pieces together, just like lego toys. The unbalanced transaction pieces end up balancing each other; no outputs need to be changed. |
Got it, thx |
Co-authored-by: Robert Phair <rphair@cosd.com>
be built up as well. Duplicate executions should be removed. For example, if two transaction pieces | ||
look to spend the same smart contract input using the same redeemer, there is no reason to evaluate | ||
this scenario twice since they are guaranteed to have the same result. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a very promising design indeed! I am curious to understand how minting NFTs that require the spending of a specific UTxO entry would work, if two pieces are trying to mint the same NFT? Would you be able to locally test if your NFT contract validates?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am curious to understand how minting NFTs that require the spending of a specific UTxO entry would work, if two pieces are trying to mint the same NFT? Would you be able to locally test if your NFT contract validates?
Hmm, I hadn't thought about testing just a piece, but it should be possible since a transaction piece is just a transaction body. This would just require a smart contract to be able to run against an unbalanced transaction body. Whether the smart contract would still succeed when aggregated with other pieces depends on the smart contract logic. So Alice can verify her piece will successfully validate before she signs, and the aggregator can verify it will still validate after adding it to the batch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, it opens up the possibility of an attack if the outcome of contract validation can be changed after you submit your transaction or transaction piece. I see two ways to deal with this :
-
restrict your design to only allow combining pieces that contain no Plutus smart contracts whatsoever
-
simplify Validation Zones to be more in line with what you are suggesting/be more implicit with value flow :
- revert changes to the UTxO rule, UTxO State, and Transaction data structures (leave them the same as in the current non-zone ledger design)
- remove new Plutus version requirement
- move the
produced = consumed
computation to the ZONE rule, and aggregate across all transactions in the zone, that isSum_{tx \in zone} consumed tx = Sum_{tx \in zone} produced tx
- replace the cycle detection in the ZONE rule by in independency check, which checks that "for all inputs
(txid, ix)
in all transactions in a zone,txid
is not the ID of another transaction in the zone - only require the per-transaction component of the transaction fee to be paid once per zone
The validation zones simplification will all remove the need for the weird requireTxs
song and dance, and an aggregator would be able to spend their liquidity pool once per zone to provide any missing value and claim any extra value within a single transaction. Scripts would operate without any changes. Flash loan attacks would be prevented by the independency check.
I believe this achieves what you are trying to do, @fallen-icarus , without compromising contract validation, by retaining the property that you cant tamper with transactions (and therefore their contract outcomes) without invalidating them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it opens up the possibility of an attack if the outcome of contract validation can be changed after you submit your transaction or transaction piece.
Only an individual piece is susceptible to this. The transaction batch is set upon submission to the blockchain and the determinism of the eUTxO model guarantees this can't happen to submitted transactions.
There is also another choice: if the user is looking to use a smart contract in a transaction piece and the user does not control the final batch, the user should accept the risk that the smart contract validation will change.
I do not believe all risks need to be eliminated. I think only the non-obvious ones need to be eliminated. The risk you bring up is a very obvious risk. When users place market orders, they accept the risk of slippage due to not controlling what the actual trade will be. How is this any different?
If the user actually wants to guarantee the smart contract validation will be a certain way, they can either:
- Write the smart contract to be agnostic to other pieces - DApp developers already do something like this to securely support DApp compositions and prevent double satsifaction.
- Create the batch themselves.
Both of your suggestions have trade-offs that I think are too extreme:
- Not allowing smart contracts whatsoever would make it impossible to balance these pieces against DApp liquidity sources. This would cut these batches off from a huge amount of liquidity.
- AFAIU the changes to Validation Zones would still not be able to properly model unbalanced intents which means all of the counter-party problems (and extra complexity) still exist. (Please correct me if I am wrong; it is sometimes hard to follow the jargon.)
I'm still open to ideas, but I really don't think people need this much hand-holding.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
The difference between an account-based dApp doing things and the Boolean outcome of an EUTxO contract is that the dApp can (and has to) be written in a way that accommodates any possible account state to which it can be applied, eg price changes etc. An EUTxO contract fee cannot even be calculated without the complete fixed transaction data. You can make any contract fail (with no negative consequences for yourself) by bulking up the tx size. If you make a transaction that is valid, someone can always make your scripts fail by submitting it batched with whatever nonsense. To avoid this, you have to be able to prevent your transaction from being modified (this is currently possible only by signing it with a key that is required to sign it). Note that even if you yourself didn’t include collateral, and are relying on someone else to include it, the transaction batch they construct can also be messed up. This brings me to the Validation Zones modification -
-
The change I propose actually allows you to model unbalanced intents by allowing whole transactions that are unbalanced, while the zones containing transactions must be balanced. It is somewhere in between the original design and what you propose. Instead of requests and fulfills, it simply allows assets to be missing from or be extra in a transaction. The preservation of value at the zone level ensures that regardless of who provides the missing assets and claims the extra ones , things balance out. Consider zone [Tx1; Tx2]
Tx1 -
(Resolved) inputs: txIn -> (10 Ada, …)
Outputs:(5PolinaCoin, …)
Tx2 -
(Resolved) inputs :txIn’ -> (5PolinaCoin, …)
Outputs :(10Ada, …)
The important thing is that txIn’
is not = (hash (Tx1), _)
, because of flash loans. No need to request 5 PolinaCoin or make an unlocked offer of 10Ada.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
i think it will not be possible to specify a fee of 0 (this is because the amount of fee specified in each transaction must go to the fee pot, and that's how the system knows how much to add), but it does not mean you have to provide the fee. Your transaction can simply be short that amount, and someone else's transaction needs to have that amount extra to make a valid zone
-
the flash loan problem here really has to do with smart contracts : you should not be able to use a thread token or a role token in your transaction unless you spend an actual output containing one. If we allow transactions in a zone to be chained in this way, you dont actually need to spend a real output with a role token to use one, flash-loaning yourself one :
Tx1 -
(Resolved) inputs : txIn -> (out1)
Outputs: (1RoleToken, …) , (out2)
where out1 and out2 are some outputs containing the state of some contract which can only be updated (from out1 to out2) if the transaction contains a RoleToken that allows such an update to be made. We are assuming here that out1 and out2 both have no assets in them for simplicity of example
Tx2 -
(Resolved) inputs : (hash (Tx1), 1) -> (1RoleToken, …)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should not be able to use a thread token or a role token in your transaction unless you spend an actual output containing one.
Perhaps I misunderstood what you meant by (hash (Tx1), _)
. I may also be misunderstanding what you mean by
(Resolved) inputs: txIn -> (out1)`.
The way I am thinking about it, the role token requirement is guaranteed to be true; there is no way to NOT spend the role token. No "resolving" is required.
A zone is just a list of transaction: [tx1, tx2, tx3]
. But we can force a dimension of time on the list:
---- Time ---->
[tx1, tx2, tx3]
If we do this, then the above is just a mini-blockchain, and we can treat it as such. The zone can build up its own mini UTxO set, and transactions in the zone have access to the current state of real UTxO set + zone UTxO set
at the time they are being processed. The zone can keep track of both the UTxOs spent from the real UTxO set and the UTxOs created/spent from the zone UTxO set. When all transactions in the zone have been fully validated, the net affect of the real UTxO set + the zone UTxO set is what actually gets applied to the blockchain.
In the above zone, tx1
gets processed first. Imagine if tx1
spends a real output r1
and produces an output z1
. The zone would log that r1
has been spent from the real UTxO set and z1
has been added to the zone UTxO set. tx2
comes after tx1
and can spend any remaining UTxO in the real UTxO set and the zone UTxO set. So tx2
cannot spend r1
because it was already spent by tx1
, but it can spend both r2
(another input from the real set) and z1
to produce z2
. tx2
would call z1
explicitly by output reference: (hash(tx1), z1_index)
. z1_index
is its index in tx1
's output list.
Now the new state is the real UTxO set minus r1
and r2
, plus the zone UTxO set of z2
. tx3
comes after tx2
so it must use this new state. If it wants to spend z2
, it must call it explicitly by output reference: (hash(tx2), z2_index)
. z2_index
is its index in tx2
's output list. Let's say tx3
spends z2
and produces z3
. tx3
cannot spend z1
because it was already spent by tx2
.
The net effect of this zone is r1
and r2
are both spent to produce z3
. This is the change that would actually be recorded on the blockchain.
With this method, if the role token was in r1
, tx1
moved it to z1
. If tx2
wants to execute the smart contract that requires the role token, it must now spend z1
because that is where the token is at the time tx2
is being processed. If tx3
wants to use the role token as well, it must spend z2
since that is where tx2
moved the token to. Because time is enforced on the zone, the zone can know where the role token is at all times. When z3
is actually recorded on-chain, it is the result of r1
-> z1
-> z2
-> z3
. The eUTxO model guarantees the result is the same as doing the updates separately (ie, in separate zones).
Important
With this approach, building a transaction chain requires coordination between the transactions in the chain. However, I am making the assertion that: coordination is always possible whenever transaction chaining is useful. If we accept this assertion, there is no need for any "resolving", and flash loans are impossible.
Strangers can't build up chains this way since they don't know each others' transactions (and therefore each others' output references), but why would strangers be chaining their transactions anyway? This is mainly useful for account style DApps that are controlled by batchers.
A batcher can personally build up the chain when trying to fulfill the user orders. They can create tx1
first and use its hash in tx2
, and then use tx2
's hash in tx3
. Furthermore, since the batcher knows the order of the outputs in each transaction, they know what the resulting output references will be in advance. The batcher can even turn the user orders into chains (if the user transactions allow for it). If batchers need to build up a chain together, they can coordinate this off-chain.
Because the outputs are being called explicitly by output reference, it is trivial to check if the role token is actually being spent. The smart contracts don't even need to know they are being executed in a zone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think it will not be possible to specify a fee of 0 (this is because the amount of fee specified in each transaction must go to the fee pot, and that's how the system knows how much to add)
I don't see why it is possible for the zone to know if it is balanced, but not know if it has enough ADA provided for the fee. The zone checks should have everything they need to calculate the total required fee for the zone, and it can compare this against the sum of the fee specified in each transaction within the zone. This would enable some transactions to have a fee of zero while still being part of a valid zone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see why it is possible for the zone to know if it is balanced, but not know if it has enough ADA provided for the fee.
This is maybe possible? Removing the per-transaction fee check (in favour of a per-zone check) is likely possible, and if we do, entering a paid fee of 0 for a transaction would also be possible. I need to think more about this, though, and would be happy to discuss in CIP meeting.
I think i need a diagram for your previous comment ...
Here is a draft of the "Implicit Value Flow" validation zones version, it is much simpler than the original
1fd1d6d#diff-560051716ec259fa49b3ef402bb6c1f4b7517d1bf400db3e735996986398bf96
ps do not follow the links to the prototype or Agda spec (they're not done)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AndrewWestberg @WhatisRT if you feel like having a look also
Discussions: | ||
- https://github.com/cardano-foundation/CIPs/pull/862#discussion_r1700138228 | ||
- https://github.com/cardano-foundation/CIPs/pull/862#issuecomment-2266689423 | ||
Solution-To: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solution-To: |
adding to the header will break downstream tools
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed to assign number in today's CIP meeting mainly due to the good documentation & the specific, practical nature of the proposal.
@@ -0,0 +1,530 @@ | |||
--- | |||
CIP: ???? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CIP: ???? | |
CIP: 130 |
Please also retitle containing directory to CIP-0130
and update the rendered proposal link in your OP 🎉
I like this concept very much. Very elegant. |
Right, I think by controlling the order of pieces, we already get most of the efficiency gain I was talking about! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately I see way too many problems with this proposal:
- change of transaction structure that would require a rewrite of half of the ledger implementation
- Idea of combining transactions (pieces) into one is just not sound. The common argument that is given in the CIP of rejecting any transactions that are incompatible in some way is way too dangerous and very hard to implement and foresee all the incompatibilities. Most importantly by changing the transaction structure through this combination process you'd be changing the content that users have signed. Which can't be allowed. In other words, transactions do not have a lawful
Semigroup
instance 😉 - No protection against transaction reordering
It might sound like I am bashing this CIP, but I am definitely not. I am pointing out the problems. There are few ideas I really like. For example the idea of having a list of transaction that are individually signed, but then combined together by a third part is pretty cool.
So, I've tried to understand this CIP as well as @polinavino's Validation Zones | CIP-118 as much as I could. And here is my attempt at an alternative solution: Transaction Swaps It is a vastly different solution, but it has the same spirit, so hopefully you'll find it satisfactory.
transaction = | ||
[ transaction_pieces : [* transaction_piece] | ||
, bool | ||
, auxiliary_data / null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which transaction_piece would contain the auxDataHash
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought I mentioned that, but I guess I accidentally deleted that part while editing. Each piece can specify it, but if multiple do, they must all agree. I wasn't anticipating users to use pieces for storing metadata on-chain. I thought they would build a personal transaction for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it is the "must agree" thing sprinkled throughout the CIP that I really have a problem with. Because of those agreements would have to be enforced by the ledger rules. Which increases complexity of already very complex rules.
- If two transaction pieces require the same witness (ie, both pieces require a signature from | ||
Alice), this witness would now effectively appear twice. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Public keys would appear twice, but signatures would be different since they would be signing different content.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that is what I meant by "effectively", but I could have been more explicit.
credential, etc), so no one can control the order of them. | ||
|
||
> [!IMPORTANT] | ||
> This would required [CIP-128](https://github.com/cardano-foundation/CIPs/pull/758) since the order |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
> This would required [CIP-128](https://github.com/cardano-foundation/CIPs/pull/758) since the order | |
> This would require [CIP-128](https://github.com/cardano-foundation/CIPs/pull/758) since the order |
|
||
### Phase 1 Validation | ||
|
||
Phase 1 validation must be slightly changed to check: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a severe understatement. Many of the ledger rules would have to be changed and restructured to accommodate validation of these new type of transactions.
So "slightly changed" does not even begin to describe the amount of work that will be needed.
} | ||
|
||
transaction = | ||
[ transaction_pieces : [* transaction_piece] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a backwards incompatible change to a transaction.
When combining the transaction pieces, the required executions (ie, script + datum + redeemer) can | ||
be built up as well. Duplicate executions should be removed. For example, if two transaction pieces | ||
look to spend the same smart contract input using the same redeemer, there is no reason to evaluate | ||
this scenario twice since they are guaranteed to have the same result. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can you spend the same input twice? That would go totally against all guarantees we provide in ledger 😄
Now, if you meant two different inputs that are locked by the same script and they expect the same datums, then you are totally wrong that they are guaranteed to have the same outcome. Each script gets the script purpose that uniquely identifies which input being spent and that could easily affect the outcome of the script.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can you spend the same input twice?
You wouldn't. You would remove duplicates when merging the pieces. If you have a list [1,2,3,4]
and another [2,5,6]
merging them (and removing duplicates) would give [1,2,3,4,5,6]
. So input 2
is listed twice, but only spent once.
Smart contracts are a definite weak-point of this CIP, but the new Validation Zones revision seems to address this weak-point while still incorporating the main ideas from this CIP. I personally prefer the new Validation Zones CIP over my own for this reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You would remove duplicates when merging the pieces
So, as I said you can't remove duplicates because of smart contracts.
And with validation zones you can't have duplicates.
would be executed against the full transaction. This requirement enables the current smart contract | ||
interface to remain mostly untouched. The flow is essentially: | ||
|
||
1. Deterministically derive the whole transaction from the list of pieces. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't deterministically derive a new transaction out of many separate ones. I'll just give you couple of counterexamples:
- two transactions that withdraw from the same reward account. It is irrelevant that one of them will be zero, it will change semantics. Moreover if a stake credential is a scritp, then how can you ignore running one of them.
- A DRep casting a yes vote on a proposal in one transaction and then a No on the same proposal in a separate transaction. You might think that we could then ignore the first vote, since the second one replaces the first. But, what if the DRep is backed by a script and it would actually fail if we didn't ignore it.
- Two transactions minting the same asset. How do you run the script twice? You'll be forced to put squash those two mints together into one, which could affect the execution of the script.
I mean, this is just the tip of the iceberg. So, it is not just about philosophy, as @WhatisRT put it, it is a really bad idea to even attempt it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- two transactions that withdraw from the same reward account. It is irrelevant that one of them will be zero, it will change semantics. Moreover if a stake credential is a scritp, then how can you ignore running one of them.
I would argue this transaction should be rejected. I think you are over-complicating things. IMO things should either exact match or be rejected. The only exceptions are when there is a very obvious way to merge them, like with mints and validity intervals.
- A DRep casting a yes vote on a proposal in one transaction and then a No on the same proposal in a separate transaction. You might think that we could then ignore the first vote, since the second one replaces the first. But, what if the DRep is backed by a script and it would actually fail if we didn't ignore it.
This transaction would be rejected as well because the proposal vote in one piece does not exact match the proposal vote in the other. The pieces are not applied to the ledger sequentially. They are folded into a single transaction and applied as a unit.
- Two transactions minting the same asset. How do you run the script twice? You'll be forced to put squash those two mints together into one, which could affect the execution of the script.
The mints would be merged upon folding the pieces and the script would only be executed once. As I said before, smart contracts are a weak-point with this CIP. AFAIU, the new Validation Zone revision addresses this limitation by actually having smart contracts validate against the piece they are used in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not over-complicating! Those are all of the cases that would have to be addressed in the ledger rules. If we are to reject them, we need to implement specific predicate failures for each one of them that do the rejection. I can see this CIP adding more predicate failures than the total number of predicate failures that we already have today.
Validation Zone revision addresses this limitation
I am really confused here. Validation Zones is a totally different CIP. Are you trying to combine the two together somehow?
The only way I currently see combining multiple transactions into one for validation to work is if we restrict all those pieces to be completely disjoined, i.e. no common credentials.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not over-complicating!
Sorry, my confusion came from not realizing the redeemers included the execution budgets and therefore you can't do an exact match. I was under-complicating it 😅
I am really confused here. Validation Zones is a totally different CIP. Are you trying to combine the two together somehow?
The new Validation Zone revision (the README-implicit.md) is trying to incorporate the unbalanced transaction idea from this CIP. It uses them in an entirely different way than how this CIP used them.
The second question requires more consideration, but as a general rule, as long as there are no | ||
incompatibilities between transaction pieces, they can be combined into the full transaction. Any | ||
transaction that contains incompatible pieces should be rejected. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any two transactions that have plutus scripts would be immediately incompatible.
Imagine a script that relies for there to be only a single input being spent or a single output being produced. As soon as you combine two transactions together they no longer validate. However, you can't know that until you try to combine them and run the scripts
There is another fundamental problem here. Imagine those inputs in two separate transactions are both locked by scripts. Those two transactions both provide script integrity hash that have potentially been signed. But whenever you combine those two transactions together you must change their redeemers and pass those redeemer modified in the script context to plutus scripts, which is totally screwing with the data that have been signed.
So, combining multiple pieces into one transaction idea is definitely out of the window
It is valid for two separate transaction pieces in a batch to spend the same UTxOs (eg, a liquidity | ||
source UTxO). This UTxO can still only be spent once and the batch must still be fully balanced |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This not valid. Their position in the input set can affect the execution outcome of a plutus script that locks them
The order of the transaction pieces list is significant since it represents the order in which the | ||
pieces must be combined, and ultimately determines the order of the inputs and outputs. How to | ||
combine the pieces will be discussed later in the spec. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is very true. However, I can't find any security mechanism that would preserve the order of transaction pieces. There is no guarantee that man in the middle or a nefarious pool will not reorder the transaction pieces in their favor
@rphair @Ryun1 I would like to withdraw this CIP in favor of Transaction swaps. @lehins correctly pointed out fatal flaws with this design:
In my view, lehins' CIP is what I intended this one to be. |
@fallen-icarus thank you as always for your brilliant work, your insight, and your humility. I'll mark this as |
@fallen-icarus I am planning on holding a Ledger working group meeting next Monday. So please join it if you can, because we will be discussing CPS-15 and the suggested approaches at tackling it: Monday, August 12th 2024 [5pm - 6pm UTC] Anyone else interested in this topic is free to join. |
@lehins That link isn't working for me. It says: "Could not find the requested event." |
Thank you for pointing it out. I've changed the event's visibility to public
|
The link still isn't working for me 😅 You may need to also make the calendar itself public (source). |
That sucks. Google could have made this UX a bit better. Unfortunately, I can't make my calendar public, but it should not be a problem. Here is the location and time of the event: Monday, August 12th 2024 [5pm - 6pm UTC] |
@fallen-icarus @lehins I'm just assigning CIP # 131 to #880 = |
This CIP suggests enabling users to create and sign pieces of transactions that can then be communicated and batched off-chain. This batch can then be submitted as a completed transaction without requiring any coordination among users. Due to the way it works, this CIP would make Cardano's basic transaction a natural intent settlement system which means it would enable direct support for things like Babel Fees and off-chain trading. Thanks to the eUTxO model, it is able to achieve this without sacrificing any of Cardano's determinism. All that is really required for the implementation is a re-organization of the cddl.
This CIP is a potential solution to CPS-0015, and an alternative to Validation Zones and Smart Transactions.
rendered proposal